背景
SharedPreferences是Android上一个轻量级的存储类,用来保存应用
的一些常用配置。
但是使用起来还是比较繁琐的,尤其当app比较大,SharedPreferences文件以及需要保存的属性较多时,操作和维护起来很麻烦,经常在存取值的时候思考应该取哪个对应的Key值。
换种思路,我要每一个SharedPreferences文件对应一个Java实体类,存取的时候,像操作实体类一样操作SharedPreferences,像下面这样:
@Spf
public class User {
long token;
String name;
String mobile;
Boolean first;
}
链式使用:
Spf_User mSpfUser = Spf_User.create(this);
// 单数据 edit
mSpfUser.name().put("name");
String name = mSpfUser.name().get();
String mobile = mSpfUser.name().get("defaultValue");
// 清理Preferences
mSpfUser.clear();
// name 是否存在
boolean exists = mSpfUser.name().exists();
// 多数据 edit
mSpfUser.edit()
.id()
.put(124)
.name()
.put("name")
.mobile()
.remove()
.apply();
// 也可以使用commit()提交,返回boolean类型
这样的话,操作、维护工作将大大减少,当然这也是完全可以实现的!
实现思路
下面只以 String name = mSpfUser.name().get() 为例分析:
反推代码,可以想象Spf_User应该是这样的:
public class Spf_User ...{
......
public StringSpfField name() {
return new StringSpfField(sharedPreferences,"name");
}
......
}
对于StringSpfField,应该包含get()方法的实现,即:
public class StringSpfField ... {
public StringSpfField(SharedPreferences sharedPreferences, String key) {
super(sharedPreferences, key);
}
@Override
public String get(String defaultValue) {
if (defaultValue == null) {
defaultValue = "";
}
return _sharedPreferences.getString(_key, defaultValue);
}
......
}
这样最基本的操作单数据是不是就完成了?!
对于存取、清除、判断是否存在等操作也大同小异,多数据的操作稍微复杂,但原理也一样,有兴趣可以查看文章结尾的源码。
当然如果我们对每一个SharedPreferences对象都自己手动去实现岂不是也挺繁琐的,所以我用了@Spf注解,不用紧张,是编译时注解,0反射,完全不会影响性能。这里不多做介绍,文章结尾源码里都有。
引用
我将项目发布到了JCenter上,有需要的童鞋可以直接使用:
project的gradle.build里添加:
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
app的gradle.build里添加:
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'me.yokeyword.smartsharedpreferences:api:1.0.0'
apt 'me.yokeyword.smartsharedpreferences:compiler:1.0.0'
}
使用介绍
1、像实体类一样创建SharedPreferences对象XXX(参照上面 图1代码),仅定义属性即可,无须定义方法,在类上使用@Spf注解;
2、编译项目;
3、编译后生成Spf_XXX,使用Spf_XXX.create(Context context)创建实例;
4、参照上面 图2代码 使用。
注:
关于除String/int/boolean/long/float类型之外的属性,可以使用Gson转换成Json(String类型)存入,取出时再通过Gson转成对应对象。
Rx版
注:
Rx版编译生成的文件,以RxSpf_开头!
Rx版除了具有普通版全部方法外,增加了2个方法:
asObservable():将取出的数据转化为Observable
例如:
RxSpf_User.create(context)
.name().asObservable()
.subscribeOn(Schedulers.io())
.map(new Func1() {
@Override
public String call(String s) {
return "rx" + s;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(String s) {
mTvShow.setText("name: " + s);
}
})
asAction():转化为Action1,可以快速存储数据
例如:
// 如果你使用RxBinding
RxView.clicks(mBtnSave)
.map(new Func1() {
@Override
public String call(Void aVoid) {
return mEtName.getText().toString();
}
})
.doOnNext(new Action1() {
@Override
public void call(String s) {
Toast.makeText(getApplicationContext(),"保存成功",Toast.LENGTH_SHORT).show();
}
})
.subscribe(RxSpf_User.create(context).name().asAction());
Rx版引用
project的gradle.build里添加:
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
app的gradle.build里添加:
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
// 你的RxJava版本
compile 'io.reactivex:rxjava:x.x.x'
compile 'me.yokeyword.rxsmartsharedpreferences:api:1.0.0'
apt 'me.yokeyword.rxsmartsharedpreferences:compiler:1.0.0'
}
源码