OkHttp —— 自带 DiskLruCache 简介

826 阅读3分钟

DiskLruCache 它是一个在文件系统中使用限定空间的缓存。每个缓存的实体都有一个字符串作为关键字,以及一个固定大小的值。每个关键字必须遵循正则表达式 [a-z0-9_-]{1,64} 。它的值是一个连续的字节,可以理解为一个流或者文件。每个值的大小必须在 0 到 Interget.MAX_VALUE 字节之间。

0 到 Interget.MAX_VALUE 字节,这大概有 1G 左右了,所以对于一般的文本文件绰绰有余了。

对于 32 位和 64 位编译器,int 占 32 位 ( 4 字节 )

1 字节 = 8bit 即二进制中的 1111 1111

int 用 4 个字节存储,范围为 -2,147,483,648 ( -2^31 ) 到 2,147,483,647 ( 2^31-1 )

2¹⁰=1024,1024=1k,1024²=1M,1024³=1G

这个缓存的数据存储在文件系统的一个目录里。这个目录必须专有于这个缓存,也就是不能存其他数据;这个缓存可以删除或者重写在这个目录中的文件。需要注意的是,当在多个进程中同时使用同一个目录下的缓存,它将引发错误。

该缓存所处的文件系统是有大小限制的。当它超过存储字节的限制时,这个缓存将在后台移除一些实体,直到符合这个限制为止。这个限制不是严格的:在等待文件删除期间,这个缓存可能会临时超出限制。这个限制不包括文件系统的开销以及缓存日志,所以对于空间敏感的应用需要设置一个保守的大小限制。

客户端调用 eidt 方法来创建或更新一个实体的值。一个实体在同一时间只可以有一个编辑器;如果一个没有效的值被编辑,那么 edit 方法将返回空。

  • 当一个实体正被 创建 ,它是需要全量更新值的;如果有必要的话,空值也应该作为一个占位符来使用。

  • 当实体正被 编辑 ,它不需要全量更新没一个值,缓存的值即为它的上一次的值

每调用 edit 方法一次,必须与之相对的要调用一次 commit 或者 abort 方法。Committing 是具有原子性的:一次性读取全量的值,在 commit 的前后,而绝不是混合的值。

客户端可以调用 get 方法读取一个实体的快照。该读取将获取在 get 方法调用那一刻的值,也就是,在 get 调用之后发生的更新或者删除操作,都不再对返回的快照产生影响。

这个类对一些 I/O 异常时宽容的。如果在文件系统里缺失指定文件,那么与之对应的实体也将被缓存丢弃。如果在写入的过程中出现异常,这个编辑器将默认失败。调用者需要处理其他的一些问题,通过捕获 IO 异常,并作出合适的应对。

DiskLruCache 中有一个叫 journalFile 的日志文件,它主要是用来实现 LRU (Least Recently Used 即:最近最少使用)

看下面 DiskLruCache.Entry 这段源码,就可以知道 OkHttp 默认的 Cache 为何有一个 .0 和 一个 .1 结尾的两份缓存 ENTRY_METADATA 和 ENTRY_BODY 了