每日一问:谈谈 SharedPreferences 的 apply() 和 commit() (2)

可以看到,又采用了一个 ArrayMap 来存放文件和 SharedPreferencesImpl 组成的键值对,然后通过通过单例的方式返回一个 SharedPreferences 对象,实际上是 SharedPreferences 的实现类 SharedPreferencesImpl,而且在其中还建立了一个内部缓存机制。

所以,从上面的分析中,我们能知道 对于一个相同的 name,我们获取到的都是同一个 SharedPreferencesImpl 对象。

SharedPreferencesImpl

在上面的操作中,我们可以看到在第一次调用 getSharedPreferences 的时候,我们会去构造一个 SharedPreferencesImpl 对象,我们来看看都做了什么。

SharedPreferencesImpl(File file, int mode) { mFile = file; mBackupFile = makeBackupFile(file); mMode = mode; mLoaded = false; mMap = null; mThrowable = null; startLoadFromDisk(); } private void startLoadFromDisk() { synchronized (mLock) { mLoaded = false; } new Thread("SharedPreferencesImpl-load") { public void run() { loadFromDisk(); } }.start(); } private void loadFromDisk() { synchronized (mLock) { if (mLoaded) { return; } if (mBackupFile.exists()) { mFile.delete(); mBackupFile.renameTo(mFile); } } // Debugging if (mFile.exists() && !mFile.canRead()) { Log.w(TAG, "Attempt to read preferences file " + mFile + " without permission"); } Map<String, Object> map = null; StructStat stat = null; Throwable thrown = null; try { stat = Os.stat(mFile.getPath()); if (mFile.canRead()) { BufferedInputStream str = null; try { str = new BufferedInputStream( new FileInputStream(mFile), 16 * 1024); map = (Map<String, Object>) XmlUtils.readMapXml(str); } catch (Exception e) { Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e); } finally { IoUtils.closeQuietly(str); } } } catch (ErrnoException e) { // An errno exception means the stat failed. Treat as empty/non-existing by // ignoring. } catch (Throwable t) { thrown = t; } synchronized (mLock) { mLoaded = true; mThrowable = thrown; // It's important that we always signal waiters, even if we'll make // them fail with an exception. The try-finally is pretty wide, but // better safe than sorry. try { if (thrown == null) { if (map != null) { mMap = map; mStatTimestamp = stat.st_mtim; mStatSize = stat.st_size; } else { mMap = new HashMap<>(); } } // In case of a thrown exception, we retain the old map. That allows // any open editors to commit and store updates. } catch (Throwable t) { mThrowable = t; } finally { mLock.notifyAll(); } } }

注意看我们的 startLoadFromDisk 方法,我们会去新开一个子线程,然后去通过 XmlUtils.readMapXml() 方法把指定的 SharedPreferences 文件的所有的键值对都读出来,然后存放到一个 map 中。

而众所周知,文件的读写操作都是耗时的,可想而知,在我们第一次去读取一个 SharedPreferences 文件的时候花上了太多的时间会怎样。

SharedPreferences 的读取操作

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyfpx.html