基於apt實現的Android快速持久化框架:AptPreferences

来源:http://www.cnblogs.com/taoweiji/archive/2016/08/08/5748039.html
-Advertisement-
Play Games

AptPreferences是基於面向對象設計的快速持久化框架,目的是為了簡化SharePreferences的使用,減少代碼的編寫。可以非常快速地保存基本類型和對象。AptPreferences是基於APT技術實現,在編譯期間實現代碼的生成,支持混淆。根據不同的用戶區分持久化信息。 特點 1. 把 ...


AptPreferences是基於面向對象設計的快速持久化框架,目的是為了簡化SharePreferences的使用,減少代碼的編寫。可以非常快速地保存基本類型和對象。AptPreferences是基於APT技術實現,在編譯期間實現代碼的生成,支持混淆。根據不同的用戶區分持久化信息。

特點

  1. 把通過的Javabean變成SharedPreferences操作類
  2. 支持保存基本類型及對象
  3. 支持根據不同的用戶區分持久化信息。

簡單例子

定義javabean類
@AptPreferences
public class Settings {
   private long loginTime;
   private LoginUser loginUser;
    // get、set方法
}
使用方式
//初始化
AptPreferencesManager.init(this, null);
// 保存信息
SettingsPreference.get().setLoginTime(System.currentTimeMillis());
SettingsPreference.get().set(new LoginUser("Wiki"));
// 獲取信息
long loginTime = SettingsPreference.get().getLoginTime();
LoginUser loginUser = SettingsPreference.get().getLoginUser();

從上面的簡單例子可以看到,我們需要做SharePreferences持久化,僅僅定義一個簡單的javabean類(Settings)並添加註解即可,這個框架會根據javabean生成帶有持久化功能的SettingsPreference類,通過這個類就可以非常簡單去保持或者獲取數據,大大簡化了SharePreferences的使用,也可以保持對象。

項目地址

https://github.com/joyrun/AptPreferences

一、配置項目

配置項目根目錄 build.gradle
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:1.5.0"
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}
配置app build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

//...
dependencies {
    compile 'com.github.joyrun.AptPreferences:aptpreferences:0.4.4'
    apt 'com.github.joyrun.AptPreferences:aptpreferences-compiler:0.4.4'
}

二、定義持久化Javabean

使用方法非常簡單,先編寫一個普通帶getter、setter的javabean類,在類頭部添加@AptPreferences即可


@AptPreferences
public class Settings {
   private long lastOpenAppTimeMillis;
   // 使用commit提交,預設是使用apply提交,配置預設值
   @AptField(commit = true)
   private String useLanguage = "zh";
   // 使用preferences的方式保存
   @AptField(preferences = true)
   private Push push;
   // 使用對象的方式保存
   private LoginUser loginUser;
   // 不持久化該欄位,僅僅保留在記憶體
   @AptField(save = false)
   private long lastActionTimeMillis;

    // ...

    // get、set方法必須寫
}

三、註解及使用說明

我們提供了兩個註解@AptPreferences和@AptField(commit = false,save = true,preferences = false)。

@AptPreferences

被註解的javabean必須為欄位實現setter和getter方法;

@AptField

AptField有三個參數可以配置。

  1. commit:可以配置使用commit還是apply持久化,預設是apply,需要在一些需要立刻保存到文件的可以使用commit方式,比如在退出APP時保存退出的時間。

  2. save:用來聲明是否需要持久化這個欄位。

  3. preferences:這個屬性僅僅適用於對象類型的欄位,用來聲明這個是以對象的方式保存,還是以preferences的方式保存。如果是true,就可以通過settingsPreference.getPush().isOpenPush()的方式存取。
  4. global:預設是true,如果設置為false時,和AptPreferencesManager.setUserInfo()配合,可以為不同的用戶進行持久化,達到每個用戶有不用的設置。

四、初始化

使用之前要進行初始化,建議在Application進行初始化,需要需要保存對象,還需要實現對象的解析器,這裡使用Fastjson作為實例:


public class MyApplication extends Application{
   @Override
   public void onCreate() {
       super.onCreate();
       AptPreferencesManager.init(this, new AptParser() {
           @Override
           public Object deserialize(Class clazz, String text) {
               return JSON.parseObject(text,clazz);
           }
           @Override
           public String serialize(Object object) {
               return JSON.toJSONString(object);
           }
       });
   }
}

五、根據不同的用戶設置

如果app支持多用戶登錄,需要根據不用的用戶持久化,可以通過下麵方法配置。再通過@AptField(global = false),就可以針對某個欄位跟隨用戶不同進行持久化。

AptPreferencesManager.setUserInfo("uid");

六、代碼調用


// 普通類型保存
SettingsPreferences.get().setUseLanguage("zh");
SettingsPreferences.get().setLastOpenAppTimeMillis(System.currentTimeMillis());
// 對象類型保存
Settings.LoginUser loginUser = new Settings.LoginUser();
loginUser.setUsername("username");
loginUser.setPassword("password");
SettingsPreferences.get().setLoginUser(loginUser);
// 對象類型帶 @AptField(preferences = true) 註解的保存,相當於把 push相關的放在一個分類
SettingsPreferences.get().getPush().setOpenPush(true);


// 獲取
String useLanguage = settingsPreference.getUseLanguage();
Settings.LoginUser loginUser1 = settingsPreference.getLoginUser();
boolean openPush = settingsPreference.getPush().isOpenPush();

七、預設值

很多時候我們需要在沒有獲取到值時使用預設值,SharedPreferences本身也是具備預設值的,所以我們也是支持預設值配置。分析生成的代碼可以看到:


@Override
public long getLastOpenAppTimeMillis() {
   return mPreferences.getLong("lastOpenAppTimeMillis", super.getLastOpenAppTimeMillis());
}

如果沒有獲取到值,會調用父類的方法,那麼就可以通過這個方式配置預設值:


@AptPreferences
public class Settings {
   // 使用commit提交,預設是使用apply提交,配置預設值
   @AptField(commit = true)
   private String useLanguage = "zh";

   // ...

}

八、詳細轉換代碼


@AptPreferences
public class Settings {
   private long lastOpenAppTimeMillis;
   // 使用commit提交,預設是使用apply提交,配置預設值
   @AptField(commit = true)
   private String useLanguage = "zh";
   // 使用preferences的方式保存
   @AptField(preferences = true)
   private Push push;
   // 使用對象的方式保存
   private LoginUser loginUser;
   // 不持久化該欄位,僅僅保留在記憶體
   @AptField(save = false)
   private long lastActionTimeMillis;
   public long getLastActionTimeMillis() {
       return lastActionTimeMillis;
   }
   public void setLastActionTimeMillis(long lastActionTimeMillis) {
       this.lastActionTimeMillis = lastActionTimeMillis;
   }
   public LoginUser getLoginUser() {
       return loginUser;
   }
   public void setLoginUser(LoginUser loginUser) {
       this.loginUser = loginUser;
   }
   public long getLastOpenAppTimeMillis() {
       return lastOpenAppTimeMillis;
   }
   public void setLastOpenAppTimeMillis(long lastOpenAppTimeMillis) {
       this.lastOpenAppTimeMillis = lastOpenAppTimeMillis;
   }
   public String getUseLanguage() {
       return useLanguage;
   }
   public void setUseLanguage(String useLanguage) {
       this.useLanguage = useLanguage;
   }
   public Push getPush() {
       return push;
   }
   public void setPush(Push push) {
       this.push = push;
   }
   public static class Push {
       private boolean openPush;
       private boolean vibrate;
       private boolean voice;
       public boolean isOpenPush() {
           return openPush;
       }
       public void setOpenPush(boolean openPush) {
           this.openPush = openPush;
       }
       public boolean isVibrate() {
           return vibrate;
       }
       public void setVibrate(boolean vibrate) {
           this.vibrate = vibrate;
       }
       public boolean isVoice() {
           return voice;
       }
       public void setVoice(boolean voice) {
           this.voice = voice;
       }
   }
   public static class LoginUser implements Serializable{
       public String username;
       public String password;
       public String getUsername() {
           return username;
       }
       public void setUsername(String username) {
           this.username = username;
       }
       public String getPassword() {
           return password;
       }
       public void setPassword(String password) {
           this.password = password;
       }
   }
}

實際上就是根據上面的代碼自動生成帶有持久化的代碼,可以在這裡可以找到

app/build/generated/source/apt/debug


public final class SettingsPreferences extends Settings {
   public static final Map<String, SettingsPreferences> sMap = new java.util.HashMap<>();
   private final SharedPreferences.Editor mEdit;
   private final SharedPreferences mPreferences;
   private final String mName;
   public SettingsPreferences(String name) {
       mPreferences = AptPreferencesManager.getContext().getSharedPreferences("Settings_" + name, 0);
       mEdit = mPreferences.edit();
       this.mName = name;
       this.setPush(new PushPreferences());
   }
   @Override
   public Settings.LoginUser getLoginUser() {
       String text = mPreferences.getString("loginUser", null);
       Object object = null;
       if (text != null) {
           object = AptPreferencesManager.getAptParser().deserialize(com.thejoyrun.aptpreferences.Settings.LoginUser.class, text);
       }
       if (object != null) {
           return (com.thejoyrun.aptpreferences.Settings.LoginUser) object;
       }
       return super.getLoginUser();
   }
   @Override
   public void setLoginUser(Settings.LoginUser loginUser) {
       mEdit.putString("loginUser", AptPreferencesManager.getAptParser().serialize(loginUser)).apply();
   }
   @Override
   public long getLastOpenAppTimeMillis() {
       return mPreferences.getLong("lastOpenAppTimeMillis", super.getLastOpenAppTimeMillis());
   }
   @Override
   public void setLastOpenAppTimeMillis(long lastOpenAppTimeMillis) {
       mEdit.putLong("lastOpenAppTimeMillis", lastOpenAppTimeMillis).apply();
   }
   @Override
   public String getUseLanguage() {
       return mPreferences.getString("useLanguage", super.getUseLanguage());
   }
   @Override
   public void setUseLanguage(String useLanguage) {
       mEdit.putString("useLanguage", useLanguage).commit();
   }
   public static SettingsPreferences get(String name) {
       if (sMap.containsKey(name)) {
           return sMap.get(name);
       }
       synchronized (sMap) {
           if (!sMap.containsKey(name)) {
               SettingsPreferences preferences = new SettingsPreferences(name);
               sMap.put(name, preferences);
           }
       }
       return sMap.get(name);
   }
   public static SettingsPreferences get() {
       return get("");
   }
   public void clear() {
       mEdit.clear().commit();
       sMap.remove(mName);
   }
   public static void clearAll() {
       java.util.Set<String> keys = sMap.keySet();
       for (String key : keys) {
           sMap.get(key).clear();
       }
   }
   private class PushPreferences extends Settings.Push {
       @Override
       public boolean isOpenPush() {
           return mPreferences.getBoolean("Push.openPush", super.isOpenPush());
       }
       @Override
       public void setOpenPush(boolean openPush) {
           mEdit.putBoolean("Push.openPush", openPush).apply();
       }
       @Override
       public boolean isVibrate() {
           return mPreferences.getBoolean("Push.vibrate", super.isVibrate());
       }
       @Override
       public void setVibrate(boolean vibrate) {
           mEdit.putBoolean("Push.vibrate", vibrate).apply();
       }
       @Override
       public boolean isVoice() {
           return mPreferences.getBoolean("Push.voice", super.isVoice());
       }
       @Override
       public void setVoice(boolean voice) {
           mEdit.putBoolean("Push.voice", voice).apply();
       }
   }
}

License

Copyright 2016 Joyrun, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 先分析做題思路 一、佈局 1.因為剛剛學到表格佈局,所以首先把頁面劃分為幾個部分 2.經過觀察,發現這個表格可以分為6行,先把table和tr弄好 3、把每一行的元素寫上 (1)第一行 可以分為兩列 第一列:一張圖片 第二列:一行超鏈接(我用p包含),自動換行後,一個輸入框,一個普通按鈕 (2)第二 ...
  • 文本陰影text-shadow屬性特效: 1.右下角陰影,左下角陰影,左上角陰影,右上角陰影 文字效果為: 如果將text-shadow改成:text-shadow:-10px 10px #333 ,就將出現左下角陰影 將text-shadow改成:text-shadow:-10px -10px # ...
  • Node.js v6.3.1 Documentation https://nodejs.org/dist/latest-v6.x/docs/api/​ npm官網 https://www.npmjs.com/​ 菜鳥教程nodejs http://www.runoob.com/nodejs/node ...
  • meta標簽作用 META標簽是HTML標記HEAD區的一個關鍵標簽,提供文檔字元集、使用語言、作者等基本信息,以及對關鍵詞和網頁等級的設定等,最大的作用是能夠做搜索引擎優化(SEO)。 PS:便於搜索引擎機器人查找、分類,互聯網應用應該要註意。 大網站都是怎麼寫? 在瞭解這個標簽之前,我查找了各個 ...
  • 1、效果圖 2、佈局文件 3、代碼實現(方式一) 4、代碼實現(方式二) ...
  • OS X 10.11 安裝Cocoapods 出現問題的解決方法 今天嘗試用 Cocoapods安裝個第三方庫.. 輸入pod install, 發現 command not find。 WTF! 估計是升級10.11後Cocoapods被幹掉了。 我輸入 sudo gem install coco ...
  • 今天博客中的Alamofire源碼的版本是以現在最新的3.4版本為例。上篇博客系統的對NSURLSession相關的東西進行了詳細的解析,詳情請看《詳解NSURLSession》,為了就是給本篇博客打下基礎。因為AlamoFire就是對NSURLSession及其相關的東西進行了進一步的封裝,讓網路 ...
  • 前言.為什麼要升級到Greendao3.0? 1. 多人開發 以往的資料庫建表建Dao等操作要新開一個module,在統一的地方管理資料庫建表,現在可以直接寫Entity。多人開發時自己管自己的Entity即可 不用像以前衝突成狗。 2. 結構簡潔方便 以往是在寫CreateTable addEnt ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...