SharedPreferences源码解析

简介

SharedPreference 是一个轻量级的 key-value 存储框架,SharedPreference的具体实现与每个应用的上下文环境有关,每个应用有自己的单独的文件夹存放这些数据,对其他应用不可见。

SharedPreference文件都是默认存放在/data/data/< package name>/shared_prefs/目录下的

使用步骤

(1)得到SharePreference对象

  • Context类中获取SharedPreference获取对象的方式(线程安全)

    如果需要多个由名称标识的(SharedPreference)共享偏好的设置文件,使用这种构造方式,第一个参数为文件名称(没有文件就会创建一个),第二个参数用于指定操作模式,MODE_PRIVATE代表只有当前应用程序才能对此文件进行读写操作,目前其他模式已经被废除。

SharedPreferences sharedPreferences = getSharedPreferences("Student",MODE_MULTI_PROCESS);
  • Activity类中获取SharedPreference的方式
    如果只需要使用Activity的SharedPreference由于这会检索属于该 Activity 的默认共享偏好设置文件因此无需提供名称。会默认将当前活动的类名作为文件名,就可以使用下面这种构造方式,这种方式底层实现就是将第一个参数设置为getLocalClassName
sharedPreferences = getPreferences(MODE_PRIVATE);

(2)调用SharedPreference对象的edit()方法获取一个SharedPreferences.Editor对象
(3)向SharedPreferences.Editor对象中添加数据,putXXX();
(4)调用apply()方法将添加的数据提交,从而完成数据存储操作。


源码分析

获取SharedPreferences对象的过程

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

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

最终还是要看看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);
    }

新建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 IllegalStateException("SharedPreferences in credential encrypted "
                                + "storage are not available until after user is unlocked");
                    }
                }
                sp = new SharedPreferencesImpl(file, mode);
                cache.put(file, sp);
                return sp;
            }
        }
        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
   
            // If somebody else (some other process) changed the prefs
            // file behind our back, we reload it.  This has been the
            // historical (if undocumented) behavior.
            sp.startReloadIfChangedUnexpectedly();
        }
        return sp;
    }

getSharedPreferences()就是返回了File文件对应的SharedPreferenceImpl对象。

整个获取sharedPreferences的过程:首先建立文件名和File文件的一一对应关系,将数据存储在mSharedPrefsPaths中,如果mSharedPrefsPaths中有文件了,则直接使用不需要重复创建,根据File文件找到对应的SharedPreferenceImpl对象并返回。


SharedPreferencesImpl

SharedPreferencesImpl是SharedPreferences的子类,首先看一下SharedPreferences接口中的方法。

public interface SharedPreferences {
   
    public interface OnSharedPreferenceChangeListener {
   
        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
    }
    public interface Editor {
   
        Editor putString(String key, @Nullable String value);
        Editor putStringSet(String key, @Nullable Set<String> values);
        Editor putInt(String key, int value);
        Editor putLong(String key, long value);
        Editor putFloat(String key, float value);
        Editor putBoolean(String key, boolean value);
        Editor remove(String key);
        Editor clear();
        boolean commit();
        void apply();
    }
    Map<String, ?> getAll();
    @Nullable
    String getString(String key, @Nullable String defValue);
    @Nullable
    Set<String> getStringSet(String key, @Nullable Set<String>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值