LruCache源码解析
LruCache通常用来做图片缓存,通过LRU算法来缓存图片,我们来看源码是怎么实现!
构造方法
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
}
LruCache内部使用了一个LinkedHashMap来保存数据,LinkedHashMap的3个参数:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
initialCapacity:初始容量
loadFactor:不知道有什么用,载入因素,可以理解为时间,空间上性能的一个参数!
accessOrder:这个参数是用来实现LRU算法的!
sizeOf
通过复写sizeOf方法,我们可以指定每个Bitmap实体的大小
mCache = new LruCache<String, Bitmap>(maxSize) {
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
};
put
public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}
V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
if (previous != null) {
entryRemoved(false, key, previous, value);
}
trimToSize(maxSize);
return previous;
}
这里的代码思路很简单,就是key,value建值对放到LinkedHashMap中,LinkedHashMap负责将其放到首个位置,
然后移除旧的缓存!
get
public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
}
V mapValue;
synchronized (this) {
mapValue = map.get(key);
if (mapValue != null) {
hitCount++;
return mapValue;
}
missCount++;
}
/*
* Attempt to create a value. This may take a long time, and the map
* may be different when create() returns. If a conflicting value was
* added to the map while create() was working, we leave that value in
* the map and release the created value.
*/
V createdValue = create(key);
if (createdValue == null) {
return null;
}
synchronized (this) {
createCount++;
mapValue = map.put(key, createdValue);
if (mapValue != null) {
// There was a conflict so undo that last put
map.put(key, mapValue);
} else {
size += safeSizeOf(key, createdValue);
}
}
if (mapValue != null) {
entryRemoved(false, key, createdValue, mapValue);
return mapValue;
} else {
trimToSize(maxSize);
return createdValue;
}
}
get方法首先从map中去除缓存,如果存在就返回,由于LinkedHashMap是线程不安全的,所以加上synchronized关键字!
如果没有命中,通过create去创建:
protected V create(K key) {
return null;
}
create默认是空实现,如果不实现这个方法,就不会对create生成的值进行存储,接下来:
synchronized (this) {
createCount++;
mapValue = map.put(key, createdValue);
if (mapValue != null) {
// There was a conflict so undo that last put
map.put(key, mapValue);
} else {
size += safeSizeOf(key, createdValue);
}
}
synchronized代码块里面,将创建createdValue加入到缓存中,返回旧的mapValue,如果有其他线程已经put了一个key,value,就将mapValue最为命中的缓存,而不使用createdValue!
其实后面的逻辑一般来说用不到,因为我们在缓存取不到的时候就直接做其他操作了,比如网络加载,或者显示默认图片!
safeSizeOf
后面的safeSizeOf用来计算bitmap的大小,然后重置整个缓存的容量大小的!
整个LRUCache源码实现大概就是这样!