当前位置:   article > 正文

android app深度优化—Shared Preference源码详解_sharedpreference

sharedpreference

前言

SharedPreferences是Android提供的数据持久化的一种手段,适合单进程、小批量的数据存储与访问。因为SharedPreferences的实现是基于单个xml文件实现的,并且,所有持久化数据都是一次性加载到内存,如果数据过大,是不合适采用SharedPreferences存放的。而适用的场景是单进程的原因同样如此,由于Android原生的文件访问并不支持多进程互斥,所以SharePreferences也不支持,如果多个进程更新同一个xml文件,就可能存在同不互斥问题。

SharedPreferences简单使用

创建

第一个参数是储存的xml文件名称,第二个是打开方式,一般就用Context.MODE_PRIVATE;

SharedPreferences sp=context.getSharedPreferences("名称", Context.MODE_PRIVATE);
复制代码
  • 1
  • 2

写入

//可以创建一个新的SharedPreference来对储存的文件进行操作
​
SharedPreferences sp=context.getSharedPreferences("名称", Context.MODE_PRIVATE);
​
//像SharedPreference中写入数据需要使用Editor
​
SharedPreference.Editor editor = sp.edit();
​
//类似键值对
​
editor.putString("name", "string");
​
editor.putInt("age", 0);
​
editor.putBoolean("read", true);
​
//editor.apply();
​
editor.commit();
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • apply和commit都是提交保存,区别在于apply是异步执行的,不需要等待。不论删除,修改,增加都必须调用apply或者commit提交保存;
  • 关于更新:如果已经插入的key已经存在。那么将更新原来的key;
  • 应用程序一旦卸载,SharedPreference也会被删除;

读取

SharedPreference sp=context.getSharedPreferences("名称", Context.MODE_PRIVATE);
​
//第一个参数是键名,第二个是默认值
​
String name=sp.getString("name", "暂无");
​
int age=sp.getInt("age", 0);
​
boolean read=sp.getBoolean("isRead", false);
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4、检索

SharedPreferences sp=context.getSharedPreferences("名称", Context.MODE_PRIVATE);
​
//检查当前键是否存在
​
boolean isContains=sp.contains("key");
​
//使用getAll可以返回所有可用的键值
​
//Map<String,?> allMaps=sp.getAll();
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

删除

当我们要清除SharedPreferences中的数据的时候一定要先clear()、再commit(),不能直接删除xml文件;

SharedPreference sp=getSharedPreferences("名称", Context.MODE_PRIVATE);
​
SharedPrefence.Editor editor=sp.edit();
​
editor.clear();
​
editor.commit();
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • getSharedPreference() 不会生成文件,这个大家都知道;
  • 删除掉文件后,再次执行commit(),删除的文件会重生,重生文件的数据和删除之前的数据相同;
  • 删除掉文件后,程序在没有完全退出停止运行的情况下,Preferences对象所存储的内容是不变的,虽然文件没有了,但数据依然存在;程序完全退出停止之后,数据才会丢失;
  • 清除SharedPreferences数据一定要执行editor.clear(),editor.commit(),不能只是简单的删除文件,这也就是最后的结论,需要注意的地方

源码分析

获取SharedPreferences对象的过程

Context是一个抽象类,它的子类中有ContextImpl和ContextWrapper

Context mBase;
public SharedPreferences getSharedPreferences(String name, int mode) {
//这里其实调用的是ContextImpl的getSharedpreferences方法
       return mBase.getSharedPreferences(name, mode);
   }
  • 1
  • 2
  • 3
  • 4
  • 5

最终还是要看看ContextImpl中的getSharedPreferences的具体实现:

public SharedPreferences getSharedPreferences(String name, int mode) {
        //当SDK< 19时,如果文件名为null则会初始化名字为"null"
        if (mPackageInfo.getApplicationInfo().targetSdkVersion <
                Build.VERSION_CODES.KITKAT) {
            if (name == null) {
                name = "null";
            }
        }
        File file;
        synchronized (ContextImpl.class) {
        //建立了文件名和File文件的一一对应关系
            if (mSharedPrefsPaths == null) {
                mSharedPrefsPaths = new ArrayMap<>();
            }
            file = mSharedPrefsPaths.get(name);
            if (file == null) {
            //在相应的sharedPreference下新建File,保存文件名为XXX.xml
                file = getSharedPreferencesPath(name);
                mSharedPrefsPaths.put(name, file);
            }
        }
        return getSharedPreferences(file, mode);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

新建File的缓存,使用Map建立了文件名和File文件的一一对应,如果没有文件则新建,并放入Map中,如果Map中有需要的文件,则直接使用get方法取出。最终调用了ContextImpl的getSharedPreferences方法。

 public SharedPreferences getSharedPreferences(File file, int mode) {
        SharedPreferencesImpl sp;
        synchronized (ContextImpl.class) {
        //在每个包下面建立了一个File-SharedPreferencesImpl对应关系的ArrayMap
        //getSharedPreferencesCacheLocked()根据包名返回相对应包下的ArrayMap
            final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
            //从file-SharedPreferencesImpl键值对中根据当前file找到SharedPreferencesImpl实例
            sp = cache.get(file);
            //如果没有对应的SharedPreferencesImpl,就新建一个
            if (sp == null) {
            // 检查mode,如果是MODE_WORLD_WRITEABLE或者MODE_MULTI_PROCESS则直接抛异常
                checkMode(mode);
                if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
                    if (isCredentialProtectedStorage()
                            && !getSystemService(UserManager.class)
                                    .isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
                        throw new Il
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/60779
推荐阅读
相关标签
  

闽ICP备14008679号