【Android】【框架】【磁盤緩存】【SharedPreferences】

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ì)于事

  1. ?。簭膬?nèi)存取
  2. commit:直接同步執(zhí)行(同時(shí)最多執(zhí)行1個(gè)任務(wù),多余1個(gè)任務(wù),還是要入隊(duì))
  3. 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í)行

image.png

可以參考Activity ANR的堆棧

image.png

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容