前言

SharedPreferences 轻量级缓存使用众所周知。但是使用极其繁琐,那么现在来封装优化一下。

目录

目录结构

基本原理

SharedPreferences是以XML<->Map键值对的形式保存在/data/data/包名/shared_prefs文件夹下。
注意:

  • app首次使用 SP 的时候会从磁盘读取,之后缓存在内存中。
  • 区别于其他缓存,他是每次都是重新写入,之前的xml文件会被改为备份文件,如果操作成功,备份文件就会删除。

进一步了解自行查看源码。

基本使用

1
2
3
4
SharedPreferences sharedPreferences= getSharedPreferences("user",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", username);
editor.commit();

问题定义

  • edit 获取不爽,太麻烦
  • 每次获取SharedPreferences实例还需要传入name,那我要是忘了呢?
  • put时要传入key值,这要是团队协作,使用到缓存的信息,还要去查看他的key值,不科学,要是数据多了岂不更麻烦
  • 每次都要commit,就不能给他封装了嘛~~

一看就不是自己人,用它给我干活不放心啊,给他包装下~

思路与实现

  1. SharedPreferences
    先看下SharedPreferences, 他本身就是interface,一看就是采用的面向接口编程,好像在告诉我,我是干这个的,你别管我咋干的,你需要用就是了~

  2. 定义执行部分

  • 自己定义方法,创建SharedPreferences实例,实现执行,先把edit的获取包起来, 那就创建个类,通过构造函数给他实例化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class BasePreference {
    private SharedPreferences sharedPreferences;
    private SharedPreferences.Editor editor;

    public BasePreference(Context context, String name) {
    sharedPreferences = context.getSharedPreferences(name, Activity.MODE_PRIVATE);
    editor = sharedPreferences.edit();
    }
    }
  • 这样获取到了edit,使用他还要实现SharedPreferences的方法,那我就自己定义个~
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public interface ISharePreferences {

    SharedPreferences.Editor putString(String key, String value);

    SharedPreferences.Editor putStringSet(String key, Set<String> values);

    SharedPreferences.Editor putInt(String key, int value);

    SharedPreferences.Editor putLong(String key, long value);

    SharedPreferences.Editor putFloat(String key, float value);

    SharedPreferences.Editor putBoolean(String key, boolean value);

    SharedPreferences.Editor remove(String key);

    SharedPreferences.Editor clear();

    boolean commit();

    void apply();

    String getString(String key, String defValue);
    ···
    }
  • 这是使用的基本方法,给BasePreference实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class BasePreference implements ISharePreferences {
    private SharedPreferences sharedPreferences;
    private SharedPreferences.Editor editor;

    public BasePreference(Context context, String name) {
    sharedPreferences = context.getSharedPreferences(name, Activity.MODE_PRIVATE);
    editor = sharedPreferences.edit();
    }

    @Override
    public SharedPreferences.Editor putString(String key, String value) {
    return editor.putString(key, value);
    }

    @Override
    public String getString(String key, String defValue) {
    return sharedPreferences.getString(key, defValue);
    }

    @Override
    public SharedPreferences.Editor clear() {
    return editor.clear();
    }

    @Override
    public boolean commit() {
    return editor.commit();
    }

    ···
    }
  • 好像可以了
  1. 理想使用效果
  • 首先是缓存分模块,比如用户信息缓存、设置配置缓存等等
    1
    2
    3
    4
    5
    6
    7
    public class UserPreferences {

    private static final String TAG ="UserPreferences";

    public UserPreferences(Context context) {

    }
  • 然后使用不能太费劲,直接看类名就知道干啥的才行,定义功能接口
    1
    2
    3
    4
    5
    6
    7
    public interface IUserPreferences {

    String getUserName();

    void saveUserName(String value);

    }
  • 实现功能
    1
    2
    3
    public class UserPreferences implements IUserPreferences {
    ···
    }
  • 怎么用Base类好呢?
  1. 业务功能和公用功能分离
  • 正常使用执行类,还需要引入ISharePreferences接口对象,实现包装父类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public interface IPreference {

    ISharePreferences getPreferences();

    void commit();

    void clear();

    void remove(String key);
    }

    public class DefaultPreference implements IPreference {

    private ISharePreferences sharePreferences;

    public DefaultPreference(Context context, String name){
    sharePreferences = new BasePreference(context, name);
    }

    @Override
    public ISharePreferences getPreferences() {
    return sharePreferences;
    }

    @Override
    public void commit() {
    getPreferences().commit();
    }

    @Override
    public void clear() {
    getPreferences().clear().commit();
    }
    }
    • 这样公用功能和ISharePreferences对象在父类实现,还差一点,name还要传入构造函数,下面来去掉,模块类名作为name自动传入
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public class DefaultPreference implements IPreference {

      private String TAG = "DefaultPreference";
      private ISharePreferences sharePreferences;

      public DefaultPreference(Context context){
      sharePreferences = new BasePreference(context, getPreferenceName());
      }

      public String getPreferenceName() {
      return TAG;
      }

      ···
      }
  • 这样继承父类后,覆盖该方法即可,如果是多人协同使用,既能看懂,又能约束
  1. 执行和使用结合
  • 继承DefaultPreference, 同时调整Key的规范
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class UserPreferences extends DefaultPreference implements IUserPreferences {

    private static final String TAG ="UserPreferences";

    public UserPreferences(Context context) {
    super(context);
    }

    @Override
    public String getPreferenceName() {
    return TAG;
    }

    @Override
    public String getUserName() {
    return getPreferences().getString(IUserConstant.USER_NAME,null);
    }

    @Override
    public void saveUserPassword(String value) {
    getPreferences().putString(IUserConstant.USER_NAME,value).commit();
    }
    ···
  1. 缓存管理类
    大功告成?还差一步!通过管理类实现缓存类的管理,并在app启动时单例实例化,防止频繁获取缓存对象,导致内容问题。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class PreferenceManager extends BasePreferenceManager {

    private static volatile PreferenceManager instance;
    private IUserPreferences userPreferences;

    public static PreferenceManager getInstance() {
    if (instance == null) {
    synchronized (PreferenceManager.class) {
    if (instance == null) {
    instance = new PreferenceManager();
    }
    }
    }
    return instance;
    }

    public IUserPreferences getUserPreferences() {
    return userPreferences;
    }

    private void setUserPreferences(IUserPreferences userPreferences) {
    this.userPreferences = userPreferences;
    }

    public void initPreferences(Context context) {
    PreferenceManager.getInstance().setUserPreferences(new UserPreferences(context));
    }
    }

    使用效果

  2. 在Application类中初始化
    1
    PreferenceManager.getInstance().initPreferences(this);
  3. 正常使用
    1
    2
    3
    4
    5
    IUserPreferences userPreferences = PreferenceManager.getInstance().getUserPreferences();
    //保存
    userPreferences.saveUserName("Kyne");
    //获取
    String name = userPreferences.getUserName();
    舒坦~~

类图

忘了咋画了 O——O~!

代码

代码