http://www.itdecent.cn/p/9ae0f6842689?tdsourcetag=s_pctim_aiomsg
整體架構(gòu)
初始化的時(shí)候會(huì)加載整個(gè)XML到內(nèi)存中
作為內(nèi)存緩存
這也是不能跨進(jìn)程的原因,任何東西只要做緩存那就是2套數(shù)據(jù)了,即使SP做了多進(jìn)程措施也無濟(jì)于事
- ?。簭膬?nèi)存取
- commit:直接同步執(zhí)行(同時(shí)最多執(zhí)行1個(gè)任務(wù),多余1個(gè)任務(wù),還是要入隊(duì))
- apply:入隊(duì)
引起ANR的原因
取是不會(huì)有ANR的,只需要在最初加載文件的時(shí)候讀取一次即可,后續(xù)都是從內(nèi)存去取
commit直接在當(dāng)前線程執(zhí)行,雖說SP是輕量級(jí)的IO,但是至少也是IO操作,做個(gè)最簡(jiǎn)單的IO操作,也要幾百ms
apply入隊(duì)本是對(duì)此很不錯(cuò)的優(yōu)化,但是最坑的一點(diǎn)是,Activity、Service、Broadcast都會(huì)在某些條件下等待SP隊(duì)列全部執(zhí)行完成
Google美名其曰確保IO可以順利執(zhí)行

可以參考Activity ANR的堆棧

waitToFinish方法會(huì)加鎖,等待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: ");
}
}
}
}
所以解決方式是反射清理等待鎖
磁盤緩存框架選型
目前頂級(jí)項(xiàng)目很少會(huì)采用SP來進(jìn)行磁盤緩存了,其ANR是一個(gè)繞不開的坎
先不說apply引起的ANR
很多時(shí)候,很多業(yè)務(wù)場(chǎng)景,對(duì)業(yè)務(wù)即時(shí)性的要求很高,所以必須采用commit的形式去做緩存
這個(gè)時(shí)候就對(duì)緩存框架的IO速度有極高的要求了
顯然SP沒有那么高效
微信開源的MMKV是值得使用的,雖然還有一些小坑會(huì)導(dǎo)致異常的ANR,但是整體上來說,是最頂級(jí)的緩存框架
原理
上面的整體架構(gòu)有介紹原理了
也是比較易于理解,通俗易懂的
所以源碼細(xì)節(jié)這里不再過多糾結(jié)了
想學(xué)習(xí)一些并發(fā)、IO的細(xì)節(jié)可以參考 https://mp.weixin.qq.com/s/qXQQb0IxrYeAFmrvXLydmA?client=tim&ADUIN=136284008&ADSESSION=1555676164&ADTAG=CLIENT.QQ.5603_.0&ADPUBNO=26882
后記
有什么寫得錯(cuò)誤、讓人費(fèi)解或遺漏的地方,希望可以不吝賜教,我會(huì)馬上更改
學(xué)習(xí)自
https://mp.weixin.qq.com/s/qXQQb0IxrYeAFmrvXLydmA?client=tim&ADUIN=136284008&ADSESSION=1555676164&ADTAG=CLIENT.QQ.5603_.0&ADPUBNO=26882
http://www.itdecent.cn/p/9ae0f6842689