基于apt实现的Android快速持久化框架:AptPreferences

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();
       }
   }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容