1、大概
- 主要功能:资源的下载与缓存
- 参考对象:Glide(Android)和 Kingfisher(Swift)
- 缓存策略:三级缓存(内存缓存、磁盘缓存、网络缓存)
- 内存缓存和磁盘缓存的核心思想都是——LRU 算法
- 网络缓存是网络请求自带的功能
- 资源主要分为图片资源和其他资源(如音视频资源):
- 图片资源——内存缓存,磁盘缓存和网络缓存
- 其他资源——有磁盘缓存和网络缓存
2、整体的流程梳理
取
- 通过 key(url 字符串的 md5)检索资源
- 先从内存缓存中检索,若有,直接取出
- 若无,再从磁盘缓存中检索,若有,直接取出,并保存到内存缓存中
- 若无,直接下载到磁盘的指定目录下,下载成功后,保存到内存缓存中
存
- 通过 url 下载资源到磁盘的指定目录后
- 若是图片资源,下载成功后,保存到内存缓存中,比较当前内存大小和内存存储范围,超过内存存储范围,会删除最久最远使用的资源,直到当前内存大小在内存存储范围内
- 若是其他资源,会比较当前磁盘大小和磁盘存储范围,超过磁盘存储范围,会删除最久最远使用的文件,直到当前磁盘大小在磁盘存储范围内
3、具体的类实现
- 首先梳理下,主要有以下几个类:
内存缓存 - Node:存储前继节点,后续节点,和当前节点 Payload
- Payload:资源的 key 和 value,key 用于保存和检索,value 保存资源对象
- DoubleLinkedList:
- Android 中,LRU 算法可以通过 LinkedHashMap 实现,但 IOS 中,没有类似的数据结构,所以得自己实现
- 支持范型,主要提供 addHead、moveHead、removeLast 方法
- addHead:新的资源,添加到链表头部(链表头部资源代表是最近最新使用的资源)
moveHead:当检索到一个资源后,移动到链表头部
removeLast:当内存不够时,移除链表尾部的资源(链表尾部资源代表是最远最久使用的资源)
- MemoryCache:除了维护 DoubleLinkedList 外,还要维护一个 [Key:Node] 的字典
- 链表:用于维护最久最远使用的元素,到该删除的时候,知道要删除拿个资源对象
字典:用户检索,知道 key 对应的 value
- 链表:用于维护最久最远使用的元素,到该删除的时候,知道要删除拿个资源对象
磁盘缓存
- DiskCache:
- 值得一提的是 updateFileTime 方法,当从磁盘缓存中检索到某一文件后,调用此方法,更新文件的修改时间,这样一来,当磁盘大小超过次过存储范围时,就可以根据文件的修改时间排序,删除最久最远使用的文件