Open kukyxs opened 4 years ago
SharedPreferencesImpl 会将 File 文件在子线程全部加载解析到一个内存的 Map 中,而 SharedPreferences 对象又会被 ContextImpl 的 static Map 进程 Cache 操作,所以 SharedPreferencesImpl 就相当于是一个单例存储的,故而其 Map 在内存中就会持续存在,即便使用 Editor 进行修改后 commit 操作实质也是对 SharedPreferencesImpl 中 Map 进行对应操作。
//一个SharedPreferences的get操作与Editor操作对应的内存Map操作原理 final class SharedPreferencesImpl implements SharedPreferences { //用来存储该SP的所有Key-Value对 private Map<String, Object> mMap; ...... SharedPreferencesImpl(File file, int mode) { ...... //构造方法新起一个线程从磁盘加载SP文件解析XML到mMap中 startLoadFromDisk(); } ...... //通过SharedPreferences对象获取指定key的值 public int getInt(String key, int defValue) { ...... Integer v = (Integer)mMap.get(key); return v != null ? v : defValue; } ...... //通过SharedPreferences.edit()获取的Editor对象 public final class EditorImpl implements Editor { //Editor要增删改查的操作Map记录 private final Map<String, Object> mModified = Maps.newHashMap(); ...... public Editor putString(String key, @Nullable String value) { ...... mModified.put(key, value); } ...... public Editor remove(String key) { ...... mModified.put(key, this); } ...... //提交到内存mMap // Returns true if any changes were made private MemoryCommitResult commitToMemory() { ...... for (Map.Entry<String, Object> e : mModified.entrySet()) { String k = e.getKey(); Object v = e.getValue(); if (v == this || v == null) { if (!mMap.containsKey(k)) { continue; } mMap.remove(k); } else { if (mMap.containsKey(k)) { Object existingValue = mMap.get(k); if (existingValue != null && existingValue.equals(v)) { continue; } } mMap.put(k, v); } changesMade = true; if (hasListeners) { keysModified.add(k); } } //清空Editor的mModified的Map mModified.clear(); ...... } ...... //commit提交 public boolean commit() { ...... //提交到内存 MemoryCommitResult mcr = commitToMemory(); //提交到磁盘文件 SharedPreferencesImpl.this.enqueueDiskWrite( mcr, null /* sync write on this thread okay */); try { mcr.writtenToDiskLatch.await(); } catch (InterruptedException e) { return false; } finally { ...... } notifyListeners(mcr); return mcr.writeToDiskResult; } ...... } }
可以理解成一个 SpFile 对应一个单例的 SharedPreferencesImpl 对象,这个单例的 SharedPreferencesImpl 实例化时会将文件全部加载到内存中以 Map 存储,然后 Editor 操作会 new 一个新的 modifyMap,接着到了 Editor 的 commit 操作时会将 modifyMap 进行遍历增删改查到 SharedPreferencesImpl 的 Map 中,然后进行存盘操作,而 SharedPreferencesImpl 进行 getX(key) 操作时都是直接从 SharedPreferencesImpl 的 Map 中进行读取的,所以说 SharedPreferences 只适合轻量级的数据存储操作。
SharedPreferencesImpl 会将 File 文件在子线程全部加载解析到一个内存的 Map 中,而 SharedPreferences 对象又会被 ContextImpl 的 static Map 进程 Cache 操作,所以 SharedPreferencesImpl 就相当于是一个单例存储的,故而其 Map 在内存中就会持续存在,即便使用 Editor 进行修改后 commit 操作实质也是对 SharedPreferencesImpl 中 Map 进行对应操作。
可以理解成一个 SpFile 对应一个单例的 SharedPreferencesImpl 对象,这个单例的 SharedPreferencesImpl 实例化时会将文件全部加载到内存中以 Map 存储,然后 Editor 操作会 new 一个新的 modifyMap,接着到了 Editor 的 commit 操作时会将 modifyMap 进行遍历增删改查到 SharedPreferencesImpl 的 Map 中,然后进行存盘操作,而 SharedPreferencesImpl 进行 getX(key) 操作时都是直接从 SharedPreferencesImpl 的 Map 中进行读取的,所以说 SharedPreferences 只适合轻量级的数据存储操作。