DiskLruCache 源碼解析 (三)—— 寫(xiě)入緩存

上一篇我們看了 DiskLruCache open 方法
這篇我們看看寫(xiě)入緩存的過(guò)程

image.png

首先我們指定一個(gè) cacheName 就是緩存的 key 來(lái)獲取一個(gè) editor
點(diǎn)進(jìn)去看一下實(shí)現(xiàn)過(guò)程

edit 方法

再點(diǎn)進(jìn) edit 中

image.png

首先看 checkNotClosed

image.png

通過(guò)判斷 journalWriter (Writer 類)是否為空來(lái)判斷是否完成寫(xiě)入操作
在看 validateKey

image.png

這里用正則表達(dá)式檢查 key 是否符合要求的格式 必須為數(shù)字或字母格式長(zhǎng)度在1~64位之間

image.png

繼續(xù)向下 sequenceNumber 在 edit 方法中傳入了固定的 ANY_SEQUENCE_NUMBER 我們暫且跳過(guò)
接下來(lái)判斷 entry 是否為空 entry 是在 linkedHashMap 中通過(guò) key 來(lái)獲取的對(duì)象實(shí)體,如果不存在創(chuàng)建一個(gè)新的并存入 map
如果存在 并且 正在編輯中(外部已經(jīng)持有一個(gè) edit 對(duì)象) 返回空

image.png

接下來(lái),在 entry 可用的情況下,創(chuàng)建一個(gè)新的 Editor 對(duì)象并將 entry 的編輯器 賦值
接下來(lái)在 journalFile 文件中寫(xiě)入 dirty 記錄
返回 editor

image.png

接下來(lái)看看寫(xiě)入數(shù)據(jù)過(guò)程
首先我將 bitmap 轉(zhuǎn)入 editor 的輸出流中,然后調(diào)用了 editor.commit()方法

commit 方法

判斷是否存在錯(cuò)誤
如果存在錯(cuò)誤 執(zhí)行 completeEdit(editor,false) 并刪除當(dāng)前 entry
如果不存在錯(cuò)誤 直接執(zhí)行 completeEdit(editor,true)
設(shè)置 commited 為 true

completeEdit

image.png

首先進(jìn)行判斷 傳入的 editor 對(duì)應(yīng)的 entry 是否與傳入的 editor 匹配
不匹配拋出異常
接下來(lái)判斷 傳入的boolean 如果是成功 并且 entry.readable 是不可讀的
循環(huán) entry 內(nèi)的所有 value 判斷 written 標(biāo)志為 false
執(zhí)行 editor.abort() 方法并拋出異常 entry 沒(méi)有 value 值
在判斷 entry 的 dirtyFile 是否存在 不存在執(zhí)行 abort

image.png

再向下,遍歷 entry 內(nèi)的所有 value
如果執(zhí)行成功的 completeEdit
將 entry 的 value 中 dirty 文件 轉(zhuǎn)為 clean 文件 更改entry 長(zhǎng)度、尺寸。
如果執(zhí)行的失敗的 completeEdit 刪除 dirty 文件

image.png

繼續(xù)向下 redundantOpCount 計(jì)數(shù)+1
置空當(dāng)前 entry 的 editor
如果是成功的操作 在 journalFile 中寫(xiě)入 CLEAN 操作行
entry.sequenceNumber=nextSequenceNumber++ 這個(gè)還不清楚 稍后再看。
如果是失敗的的操作 在 journalFile 中寫(xiě)入 REMOVE 操作行
寫(xiě)入文件
判斷 當(dāng)前緩存容量 與 用戶設(shè)置的最大容量,或者是 rebuild 請(qǐng)求操作

image.png

如果需要 rebuild journalFile

callable 線程
trimToSize 方法

循環(huán)刪除 lru 條件的 map entry
直到尺寸小于最大緩存容量
結(jié)束寫(xiě)入流程

總結(jié)一下:
1、獲取 editor 時(shí) 會(huì)在 journal 中寫(xiě)入一條 dirty 記錄
并在 lruMap 中創(chuàng)建/復(fù)用一個(gè) entry
2、commit 方法 調(diào)用 completeEdit 方法 獲取 dirtyfile 并轉(zhuǎn)成 cleanfile
3、檢查容量是否超出限制,如果超出執(zhí)行整理操作,根據(jù) lru 刪除數(shù)據(jù)

我們還需要看一下 Entry類 這是一個(gè) DiskLruCache 的內(nèi)部類

Entry類

屬性的注釋很清楚

image.png

我們看方法列表中有兩個(gè)熟悉的身影,getCleanFile() 和 getDirtyFile()

image.png

我們看到 cleanFile 是一個(gè)以 key 與 value 索引命名的文件
而 dirtyFile 是一個(gè) tmp 文件 說(shuō)明
當(dāng)我們緩存數(shù)據(jù)時(shí) 是先將 editor 中流的數(shù)據(jù)寫(xiě)入 dirty.tmp 中
確定后再轉(zhuǎn)到 cleanFile 中
我們回過(guò)頭在看一次 completeEdit()方法中的一段代碼

image.png

寫(xiě)入數(shù)據(jù) commit 時(shí) 先判斷 dirty 是否存在,也就是判斷一下之前是否有

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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