LruCache、DiskLruCache原理

2020-11-26  本文已影响0人  momxmo

一、LruCache 原理

为什么使用它?

之前,我们会使用内存缓存技术实现,也就是软引用或弱引用,在 Android 2.3(APILevel 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。

内部逻辑原理

其实 LRU 缓存的实现类似于一个特殊的栈,把访问过的元素放置到栈顶(若栈中存在,则更新至栈顶;若栈中不存在则直接入栈),然后如果栈中元素数量超过限定值,则删除栈底元素(即最近最少使用的元素)。

技术实现原理

它的内部存在一个 LinkedHashMap 和 maxSize,把最近使用的对象用强引用存储在 LinkedHashMap 中,给出来 put 和 get 方法,每次 put 图片时计算缓存中所有图片的总大小,跟 maxSize 进行比较,大于 maxSize,就将最久添加的图片移除,反之小于 maxSize 就添加进来。

LruCache 的原理就是利用 LinkedHashMap 持有对象的强引用,按照 Lru 算法进行对象淘汰。具体说来假设我们从表尾访问数据,在表头删除数据,当访问的数据项在链表中存在时,则将该数据项移动到表尾,否则在表尾新建一个数据项。当链表容量超过一定阈值,则移除表头的数据。

详细来说就是 LruCache 中维护了一个集合 LinkedHashMap,该 LinkedHashMap是以访问顺序排序的。当调用 put()方法时,就会在结合中添加元素,并调用trimToSize()判断缓存是否已满,如果满了就用 LinkedHashMap 的迭代器删除队头元素,即近期最少访问的元素。当调用 get()方法访问缓存对象时,就会调用LinkedHashMap 的 get()方法获得对应集合元素,同时会更新该元素到队尾。

LruCache put 方法核心逻辑

在添加过缓存对象后,调用 trimToSize()方法,来判断缓存是否已满,如果满了就要删除近期最少使用的对象。trimToSize()方法不断地删除 LinkedHashMap 中队头的元素,即近期最少访问的,直到缓存大小小于最大值(maxSize)。

LruCache get 方法核心逻辑

当调用 LruCache 的 get()方法获取集合中的缓存对象时,就代表访问了一次该元素,将会更新队列,保持整个队列是按照访问顺序排序的。
为什么会选择 LinkedHashMap 呢?
这跟 LinkedHashMap 的特性有关,LinkedHashMap 的构造函数里有个布尔参数accessOrder,当它为 true 时,LinkedHashMap 会以访问顺序为序排列元素,否则以插入顺序为序排序元素。

LinkedHashMap 原理

LinkedHashMap 几乎和 HashMap 一样:从技术上来说,不同的是它定义了一个 Entry<K,V> header,这个 header 不是放在 Table 里,它是额外独立出来的。LinkedHashMap 通过继承 hashMap 中的 Entry<K,V>,并添加两个属性Entry<K,V> before,after,和 header 结合起来组成一个双向链表,来实现按插入顺序或访问顺序排序。

二、DiskLruCache 原理

DiskLruCache 与 LruCache 原理相似,只是多了一个 journal 文件来做磁盘文件的管理;

public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
上一篇下一篇

猜你喜欢

热点阅读