类比
你有了一堆数据,你怎么管理?
- MySql 对这一堆数据增删改查是小菜一碟。
- 自己写个数据管理系统
DiskLruCache可以说是一个数据管理系统。
如何管理这一堆文件?
利用 map:LinkedHashMap<String, Entry>
每个文件都有唯一的key,根据这个key来获取到这个文件。
一个问题
管理一堆文件的 map 是存放到内存中的:
要是你的应用被杀死了,内存被清除了,你还怎么去管理这一堆文件呢?
有几种方式:
- 遍历你所存储的所有文件,重建map。
- 将内存中的map存储起来。
DiskLruCache 采用第二种情况。考虑到不知道map什么时候被回收掉。它记录了对每个文件的增与删的操作。这样当DiskLruCache满血复活的时候就可以读取这些记录,将map还原啦。
对文件操作的记录
为了可以将 map 还原,我们需要记录对每个文件的操作。
1. Entry
我们用 Entry 来记录相关的一个文件
对entry的操作我们使用 editor
2. Editor
利用 editor 可以轻易的获取对应文件的 输入输出流。所以很方便操作 entry啦。最后结束时,不要忘记 commit!
为什么要commit呢?
commit 是对文件操作的补充
- 读写文件出错了,补充出错的处理。
- 读写文件完成,补充记录操作的日志。
completeEdit:
小细节,但非常重要!!!
考虑到对一个文件的写入,要是突然死机或是断电了,怎么办?
这时候的写入的这个文件肯定是脏数据,我们希望维护的是完整的,有用的清洁数据!!!
解决方案:
可以采用写入临时文件,当一切完成以后,将这个临时文件改邪归正即可。
editor 中的创建输出流:
completeEdit:
其它
on filesystem
A cache that uses a bounded amount of space on a filesystem.
** cache entry**
Each cache entry has a string key and a fixed number of values. Values are byte sequences, accessible as streams or files. Each value must be between 0 and Integer.MAX_VALUE bytes in length.
directory
The cache stores its data in a directory on the filesystem. This directory must be exclusive to the cache; the cache may delete or overwrite files from its directory. It is an error for multiple processes to use the same cache directory at the same time.
limit
This cache limits the number of bytes that it will store on the filesystem. When the number of stored bytes exceeds the limit, the cache will remove entries in the background until the limit is satisfied. The limit is not strict: the cache may temporarily exceed it while waiting for files to be deleted. The limit does not include filesystem overhead or the cache journal so space-sensitive applications should set a conservative limit.
edit
Clients call edit to create or update the values of an entry. An entry may have only one editor at one time; if a value is not available to be edited then edit will return null.
entry
When an entry is being created it is necessary to supply a full set of values; the empty value should be used as a placeholder if necessary.
When an entry is being edited, it is not necessary to supply data for every value; values default to their previous value.
commit
Every edit call must be matched by a call to DiskLruCache.Editor.commit or DiskLruCache.Editor.abort. Committing is atomic: a read observes the full set of values as they were before or after the commit, but never a mix of values.
snapshot
Clients call get to read a snapshot of an entry. The read will observe the value at the time that get was called. Updates and removals after the call do not impact ongoing reads.
some errors
This class is tolerant of some I/O errors. If files are missing from the filesystem, the corresponding entries will be dropped from the cache. If an error occurs while writing a cache value, the edit will fail silently. Callers should handle other problems by catching IOException and responding appropriately.