为什么使用LruCache缓存
首先看做一个缓存的关键步骤, 存储,读取,清理。
存储和读取区别不是很大,Lru算法做缓存和普通的数据结构做缓存相比最大的不同就是对清理策略的处理,由于空间的限制,所有的缓存都需要一个清理策略,最简单的清理策略就是定一个过期时间和一个最大空间,超过最大占用空间了, 需要进入清理流程, 还有超过过期时间的缓存内容被标记为过期,进入清理流程,所以我们需要维护一个时间字段,和一个空间最大值,当然也可以实现比较完美的缓存。
Lru缓存简单的地方在于,他只需要一个最大空间值, 而不需要自己维护过期时间,通过一些数据结构,巧妙的让每次缓存命中或者新加入的数据,排在最前面, 而后面的数据就沉淀为长时间没有使用过的数据,简单是简单了,但是可定制化和灵活性肯定是比较差的了,就比如说这个空间最大值,maxSize定多少就很关键,如果太小了,而数据量比较大,那么这个lru算法就失去意义了, 因为可能被删掉的数据也是不久前访问过的,如果maxSize定的太大了, 对空间会造成浪费,个人认为肯定是比普通的做法最大空间小,因为普通做法出发最大空间时候,一定是已经占用很多空间了,否则使用时间来管理即可满足条件。
LruCache对于热点缓存优势比较大, 一部分频繁多次使用的数据, 效率很高,例如图片缓存,一些首页之类的图片肯定是频繁的,次级页面的优先级就不高了这种场景就比较合适,而对于,偶发的散列的,周期性的数据明显是不合适的。
android sdk lrucache原理
主要使用了LinkedHashMap这个数据结构,他自己就可以制定使用访问顺序存储数据,每次put和get数据的时候,会把新数据放到双向链表的尾端,方便读取,不常用的会逐渐沉淀到头部。
public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
V previous;
synchronized (this) {
//put次数,可以通过get方法获取。
putCount++;
//size是计算一共现有多少单位的,通过sizeOf(key,value)方法得到的, 如果不重写的话会加1。
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
//如果之前有值,需要减掉他的size
size -= safeSizeOf(key, previous);
}
}
if (previous != null)