美文网首页week.ioAndroidAndroid
帅气的使用SharedPreferences(含RxJava版)

帅气的使用SharedPreferences(含RxJava版)

作者: YoKey | 来源:发表于2016-01-12 09:53 被阅读2701次

    背景

    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<String, String>() {
                @Override
                public String call(String s) {
                    return "rx" + s;
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {
                    mTvShow.setText("name:  " + s);
                }
            })
    

    asAction():转化为Action1,可以快速存储数据
    例如:

    // 如果你使用RxBinding
    RxView.clicks(mBtnSave)
            .map(new Func1<Void, String>() {
                @Override
                public String call(Void aVoid) {
                    return mEtName.getText().toString();
                }
            })
            .doOnNext(new Action1<String>() {
                @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'
    }
    
    

    源码

    GitHub地址
    Rx版GitHub地址

    相关文章

      网友评论

      • 字字珠玑:使用注解确实清爽了许多,链式调用也很赞,但是每次新增加了属性,都需要重新编译之后才能使用,也是比较耽误时间的,不知道楼主有什么好的解决办法
        Ggx的代码之旅:这是没办法的 因为使用的是编译时注解 要自动帮你生成一些类出来,你不编译 怎么去生成类,除非做到像谷歌的DataBind一样,自动创建的类 让人感觉不到
      • 柴泽建_Jack:这个和AA基本一样。单拿出来很不错,因为有的时候真的不想全用AA。
        柴泽建_Jack:@彩笔怪盗基德 Android Annotations,那个框架里都是这种注解。
        彩笔怪盗基德:@柴泽建_Jack AA是Active Android么
      • 聪葱忙忘:好想知道你这个注解是怎样实现的,有没有相关的资料参考下?
        聪葱忙忘:@YoKey 好的谢谢!
        YoKey: @聪葱忙忘 apt 编译时注解 你可以去搜索下看看~
      • RidingWind2023:注解spf的技巧颠覆了我的xx观了 博主你太有才了 给你99分 还有一分不给你怕你骄傲
        RidingWind2023:@YoKeyword 授人以鱼不如授人以渔 博主低调分享了技术获取来源 我要把剩下没给你的一分加上了 哈哈
        YoKey:@海上牧云 过奖啦 这个思路我最早是在AndroidAnnotations这个库里看到的,但是那个库太大了,我就单把很常用的Spf部分拿出来做成一个库啦~
      • HelloVass:github 的地址给错了,文章的末尾。。。
        YoKey:@HelloVass :joy:

      本文标题:帅气的使用SharedPreferences(含RxJava版)

      本文链接:https://www.haomeiwen.com/subject/lpwqkttx.html