美文网首页
SharedPreferences 的讲解以及项目中的使用

SharedPreferences 的讲解以及项目中的使用

作者: 雨霁邂逅 | 来源:发表于2018-08-04 13:02 被阅读0次

目录:

  • 简介
  • SharedPreferences使用步骤
  • 生成SharedPreferences的三种方式
  • 使用SharedPreferences注意事项
  • SharedPreferences注册监听
  • SharedPreferences的简单封装

简介:

SharedPreferences,是Android上一种轻量级数据储存方式。主要用于储存App配置信息;支持储存数据类型:boolean、int、float、long、String。


SharedPreferences使用步骤:

  1. 生成SharedPreferences对象;

  2. 生成editor对象;

  3. 由editor对SharedPreferences进行put、delete以及clear操作;

  4. commit()/apply()提交;


生成SharedPreferences的三种方式:

  1. PreferenceManager.getDefaultSharedPreferences(Context)生成:包名_preferences.xml;

  2. Activity.getPreferences(int mode)生成:Activity名.xml;

  3. Context.getSharedPreferences(String name,int mode)生成:name.xml

注:

  1. 生成的文件位置位于:data/data/包名/shared_prefs/目录下;
  2. mode一般为:MODE_PRIVATE;

使用SharedPreferences注意事项:

1. SharedPreferences文件应尽量小

SharedPreferences在创建的时候,会将整个文件加载到内存。如果文件过大,将会导致下列问题:

  1. 第一次从SharedPreferences中取值时,有可能阻碍主线程,使界面卡顿、掉帧;
  2. 解析SharedPreferences时会产生大量的临时对象,导致频繁GC,使界面卡顿;
  3. SharedPreferences中的key和value会一直存在内存中,占据大量内存;
2. 尽量少edit和apply提交
  1. 每次edit都会创建一个Editor对象,额外占据内存;
  2. 多次apply会造成界面的卡顿;
3. 不推荐使用SharedPreferences进行跨进

综上三点可以查看Android请不要滥用SharedPreference从源码上理解缘由。


SharedPreferences注册监听:

OnSharedPreferenceChangeListener是Android中SharedPreference文件发生变化的监听器。

当如下使用时:

@Override
protected void onCreate(Bundle savedInstanceState) {
  PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener(){
                @Override
                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
                    Log.i("SP-->" ,"onSharedPreferenceChanged");
                }
            });
}

总是会出现回调方法无法回调的问题,其原因为:注册的监听器使用了匿名内部类。由于listener保持在WeakHashMap中,这就意味着不能监听一个匿名内部类,因为listener会成为垃圾收集的目标,只要离开目前的作用范围,它将会被作为垃圾收集,从WeakHashMap中删除并停止工作。源码实现:

final class SharedPreferencesImpl implements SharedPreferences {
......
  ......
    ......
  @GuardedBy("mLock")
  private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
            new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
......
  ......
    ......
  public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        synchronized(mLock) {
            mListeners.put(listener, CONTENT);
        }
    }
}

解决方案:
网上有很好的解决方案,可自行查阅,在这里不再贴代码,简单说一下解决思路:

  1. 将监听器listener作为成员变量;
  2. 在onResume()中注册监听;
  3. 在onPause()中注销监听;

也有在onStart()和onStop()中注册与注销的,不过笔者个人认为在onResume()和onPause()中进行注册和注销更有利于内存的使用,还望大家斟酌使用。


SharedPreferences的简单封装:

public class SharedPreferenceUtils {

    private static SharedPreferences sharedPreferences;
    private static SharedPreferences.Editor editor;

    /**
     * 使用PreferenceManager生成SharedPreferences
     * @param context   getApplicationContext();
     * @return          sharedpreferences
     */
    private SharedPreferences getSharedPreferences(Context context){
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

    /**
     * 使用Activity生成SharedPreferences
     * @param activity   相关联的Activity
     * @param mode       文件模式
     * @return           SharedPreferences
     */
    private SharedPreferences getSharedPreferences(Activity activity,int mode){
        return activity.getPreferences(mode);
    }

    /**
     * 使用Context生成SharedPreferences
     * @param context   上下文
     * @param name      文件名
     * @param mode      文件模式
     * @return          SharedPreferences
     */
    private SharedPreferences getSharedPreferences(Context context,String name,int mode){
        return context.getSharedPreferences(name,mode);
    }

    private void put(HashMap<String,Object> data){
        editor = sharedPreferences.edit();
        Set<String> keys = data.keySet();
        for (String key : keys){
            Object value = data.get(key);
            parseValue(editor,key,value);
        }
        editor.apply();
    }

    private void put(String key, Object value) {
        editor = sharedPreferences.edit();
        parseValue(editor,key,value);
        editor.apply();
    }

    private Object getData(String key, Class<? extends Object> valueClass){

        if (valueClass.equals(Integer.class)){
            return sharedPreferences.getInt(key,0);
        }else if (valueClass.equals(String.class)){
            return sharedPreferences.getString(key,"null");
        }else if (valueClass.equals(Float.class)){
            return sharedPreferences.getFloat(key,0f);
        }else if (valueClass.equals(Boolean.class)){
            return sharedPreferences.getBoolean(key,false);
        }else if (valueClass.equals(Long.class)){
            return sharedPreferences.getLong(key,0L);
        }
        return null;
    }

    private void clear(){
        sharedPreferences.edit().clear().apply();
    }

    private void deleteData(String key){
        sharedPreferences.edit().remove(key).apply();
    }

    private void deleteData(String[] keys){
        editor = sharedPreferences.edit();
        for (String key : keys){
            editor.remove(key);
        }
        editor.apply();
    }

    private void parseValue(SharedPreferences.Editor editor,String key,Object value){
        Class<? extends Object> valueClass;
        valueClass = value.getClass();
        if (valueClass.equals(Integer.class)){
            editor.putInt(key,(int)value);
        }else if (valueClass.equals(String.class)){
            editor.putString(key,(String)value);
        }else if (valueClass.equals(Float.class)){
            editor.putFloat(key,(float)value);
        }else if (valueClass.equals(Boolean.class)){
            editor.putBoolean(key,(boolean)value);
        }else if (valueClass.equals(Long.class)){
            editor.putLong(key,(long)value);
        }
    }

    public static class Builder{

        private WeakReference<SharedPreferenceUtils> weakSPUtils;
        private SharedPreferenceUtils spUtils;

        public Builder(Context context){
            isSPUtilsEnpty();
            sharedPreferences = spUtils.getSharedPreferences(context);
        }

        public Builder(Activity activity,int mode){
            isSPUtilsEnpty();
            sharedPreferences = spUtils.getSharedPreferences(activity,mode);
        }

        public Builder(Context context,String name,int mode){
            isSPUtilsEnpty();
            sharedPreferences = spUtils.getSharedPreferences(context,name,mode);
        }

        public Builder putData(HashMap<String,Object> data){
            spUtils.put(data);
            return this;
        }

        public Builder putData(String key,Object value){
            spUtils.put(key,value);
            return this;
        }

        public Builder deleteData(String[] keys){
            spUtils.deleteData(keys);
            return this;
        }

        public Builder deleteData(String key){
            spUtils.deleteData(key);
            return this;
        }

        public Builder clear(){
            spUtils.clear();
            return this;
        }

        public Object getData(String key,Class<? extends Object> valueClass){
            return spUtils.getData(key,valueClass);
        }

        public Builder create(){
            return this;
        }

        private void isSPUtilsEnpty() {
            if (weakSPUtils.get() == null){
                weakSPUtils = new WeakReference<SharedPreferenceUtils>(new SharedPreferenceUtils());
                spUtils = weakSPUtils.get();
            }
        }

    }
}

封装支持的功能:

  1. 单个和批量添加:putData(HashMap data)、putData(key,value);
  2. 单个和批量删除:deleteData(keys)、deleteData(key);
  3. 获取数据:getData(key,valueClass);
  4. 清理数据:clear();

简单使用:
案例:批量添加数据

HashMap<String,Object> data = new HashMap<>();
   data.put("int",1);
   data.put("float",2.123f);
   data.put("String","abc");

SharedPreferenceUtils.Builder builder = new SharedPreferenceUtils.Builder(getApplicationContext())
                .putData(data)
                .create();

相关文章

网友评论

      本文标题:SharedPreferences 的讲解以及项目中的使用

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