DiskLruCache 源码解析 (三)—— 写入缓存

上一篇我们看了 DiskLruCache open 方法
这篇我们看看写入缓存的过程

DiskLruCache 源码解析 (三)—— 写入缓存_第1张图片
image.png

首先我们指定一个 cacheName 就是缓存的 key 来获取一个 editor
点进去看一下实现过程

DiskLruCache 源码解析 (三)—— 写入缓存_第2张图片
edit 方法

再点进 edit 中

DiskLruCache 源码解析 (三)—— 写入缓存_第3张图片
image.png

首先看 checkNotClosed

DiskLruCache 源码解析 (三)—— 写入缓存_第4张图片
image.png

通过判断 journalWriter (Writer 类)是否为空来判断是否完成写入操作
在看 validateKey

DiskLruCache 源码解析 (三)—— 写入缓存_第5张图片
image.png

这里用正则表达式检查 key 是否符合要求的格式 必须为数字或字母格式长度在1~64位之间

DiskLruCache 源码解析 (三)—— 写入缓存_第6张图片
image.png

继续向下 sequenceNumber 在 edit 方法中传入了固定的 ANY_SEQUENCE_NUMBER 我们暂且跳过
接下来判断 entry 是否为空 entry 是在 linkedHashMap 中通过 key 来获取的对象实体,如果不存在创建一个新的并存入 map
如果存在 并且 正在编辑中(外部已经持有一个 edit 对象) 返回空

DiskLruCache 源码解析 (三)—— 写入缓存_第7张图片
image.png

接下来,在 entry 可用的情况下,创建一个新的 Editor 对象并将 entry 的编辑器 赋值
接下来在 journalFile 文件中写入 dirty 记录
返回 editor

image.png

接下来看看写入数据过程
首先我将 bitmap 转入 editor 的输出流中,然后调用了 editor.commit()方法

DiskLruCache 源码解析 (三)—— 写入缓存_第8张图片
commit 方法

判断是否存在错误
如果存在错误 执行 completeEdit(editor,false) 并删除当前 entry
如果不存在错误 直接执行 completeEdit(editor,true)
设置 commited 为 true

completeEdit

DiskLruCache 源码解析 (三)—— 写入缓存_第9张图片
image.png

首先进行判断 传入的 editor 对应的 entry 是否与传入的 editor 匹配
不匹配抛出异常
接下来判断 传入的boolean 如果是成功 并且 entry.readable 是不可读的
循环 entry 内的所有 value 判断 written 标志为 false
执行 editor.abort() 方法并抛出异常 entry 没有 value 值
在判断 entry 的 dirtyFile 是否存在 不存在执行 abort

DiskLruCache 源码解析 (三)—— 写入缓存_第10张图片
image.png

再向下,遍历 entry 内的所有 value
如果执行成功的 completeEdit
将 entry 的 value 中 dirty 文件 转为 clean 文件 更改entry 长度、尺寸。
如果执行的失败的 completeEdit 删除 dirty 文件

DiskLruCache 源码解析 (三)—— 写入缓存_第11张图片
image.png

继续向下 redundantOpCount 计数+1
置空当前 entry 的 editor
如果是成功的操作 在 journalFile 中写入 CLEAN 操作行
entry.sequenceNumber=nextSequenceNumber++ 这个还不清楚 稍后再看。
如果是失败的的操作 在 journalFile 中写入 REMOVE 操作行
写入文件
判断 当前缓存容量 与 用户设置的最大容量,或者是 rebuild 请求操作

DiskLruCache 源码解析 (三)—— 写入缓存_第12张图片
image.png

如果需要 rebuild journalFile

DiskLruCache 源码解析 (三)—— 写入缓存_第13张图片
callable 线程
trimToSize 方法

循环删除 lru 条件的 map entry
直到尺寸小于最大缓存容量
结束写入流程

总结一下:
1、获取 editor 时 会在 journal 中写入一条 dirty 记录
并在 lruMap 中创建/复用一个 entry
2、commit 方法 调用 completeEdit 方法 获取 dirtyfile 并转成 cleanfile
3、检查容量是否超出限制,如果超出执行整理操作,根据 lru 删除数据

我们还需要看一下 Entry类 这是一个 DiskLruCache 的内部类

DiskLruCache 源码解析 (三)—— 写入缓存_第14张图片
Entry类

属性的注释很清楚

DiskLruCache 源码解析 (三)—— 写入缓存_第15张图片
image.png

我们看方法列表中有两个熟悉的身影,getCleanFile() 和 getDirtyFile()

DiskLruCache 源码解析 (三)—— 写入缓存_第16张图片
image.png

我们看到 cleanFile 是一个以 key 与 value 索引命名的文件
而 dirtyFile 是一个 tmp 文件 说明
当我们缓存数据时 是先将 editor 中流的数据写入 dirty.tmp 中
确定后再转到 cleanFile 中
我们回过头在看一次 completeEdit()方法中的一段代码

DiskLruCache 源码解析 (三)—— 写入缓存_第17张图片
image.png

写入数据 commit 时 先判断 dirty 是否存在,也就是判断一下之前是否有

你可能感兴趣的:(DiskLruCache 源码解析 (三)—— 写入缓存)