【Android】【框架】【磁盘缓存】【SharedPreferences】

https://www.jianshu.com/p/9ae0f6842689?tdsourcetag=s_pctim_aiomsg
整体架构 初始化的时候会加载整个XML到内存中
作为内存缓存
这也是不能跨进程的原因,任何东西只要做缓存那就是2套数据了,即使SP做了多进程措施也无济于事

  1. 取:从内存取
  2. commit:直接同步执行(同时最多执行1个任务,多余1个任务,还是要入队)
  3. apply:入队
引起ANR的原因 取是不会有ANR的,只需要在最初加载文件的时候读取一次即可,后续都是从内存去取
commit直接在当前线程执行,虽说SP是轻量级的IO,但是至少也是IO操作,做个最简单的IO操作,也要几百ms
apply入队本是对此很不错的优化,但是最坑的一点是,Activity、Service、Broadcast都会在某些条件下等待SP队列全部执行完成
Google美名其曰确保IO可以顺利执行
【Android】【框架】【磁盘缓存】【SharedPreferences】
文章图片
image.png
可以参考Activity ANR的堆栈
【Android】【框架】【磁盘缓存】【SharedPreferences】
文章图片
image.png waitToFinish方法会加锁,等待queue清空
public static void waitToFinish() { long startTime = System.currentTimeMillis(); boolean hadMessages = false; Handler handler = getHandler(); synchronized (sLock) { if (handler.hasMessages(QueuedWorkHandler.MSG_RUN)) { // Delayed work will be processed at processPendingWork() below handler.removeMessages(QueuedWorkHandler.MSG_RUN); if (DEBUG) { hadMessages = true; Log.d(LOG_TAG, "waiting"); } }// We should not delay any work as this might delay the finishers sCanDelay = false; }StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { processPendingWork(); } finally { StrictMode.setThreadPolicy(oldPolicy); }try { while (true) { Runnable finisher; synchronized (sLock) { finisher = sFinishers.poll(); }if (finisher == null) { break; }finisher.run(); } } finally { sCanDelay = true; }synchronized (sLock) { long waitTime = System.currentTimeMillis() - startTime; if (waitTime > 0 || hadMessages) { mWaitTimes.add(Long.valueOf(waitTime).intValue()); mNumWaits++; if (DEBUG || mNumWaits % 1024 == 0 || waitTime > MAX_WAIT_TIME_MILLIS) { mWaitTimes.log(LOG_TAG, "waited: "); } } } }

所以解决方式是反射清理等待锁
磁盘缓存框架选型 目前顶级项目很少会采用SP来进行磁盘缓存了,其ANR是一个绕不开的坎
先不说apply引起的ANR
很多时候,很多业务场景,对业务即时性的要求很高,所以必须采用commit的形式去做缓存
这个时候就对缓存框架的IO速度有极高的要求了
显然SP没有那么高效
微信开源的MMKV是值得使用的,虽然还有一些小坑会导致异常的ANR,但是整体上来说,是最顶级的缓存框架
原理 上面的整体架构有介绍原理了
也是比较易于理解,通俗易懂的
所以源码细节这里不再过多纠结了
想学习一些并发、IO的细节可以参考 https://mp.weixin.qq.com/s/qXQQb0IxrYeAFmrvXLydmA?client=tim&ADUIN=136284008&ADSESSION=1555676164&ADTAG=CLIENT.QQ.5603_.0&ADPUBNO=26882
后记 有什么写得错误、让人费解或遗漏的地方,希望可以不吝赐教,我会马上更改
学习自 【【Android】【框架】【磁盘缓存】【SharedPreferences】】https://mp.weixin.qq.com/s/qXQQb0IxrYeAFmrvXLydmA?client=tim&ADUIN=136284008&ADSESSION=1555676164&ADTAG=CLIENT.QQ.5603_.0&ADPUBNO=26882
https://www.jianshu.com/p/9ae0f6842689

    推荐阅读