开始准备先讲引用的,但是考虑到网上有很多优秀的框架,关于缓存这块基本上全是用的LruCache,所有先讲解下Lrucache的使用和源码分析。
LRU是Least Recently Used 近期最少使用算法。其实LruCache的作用就是对缓存的元素进行排序,当超过设定的内存值时就会将使用最少,使用最早元素先回收。
LruCache的声明:
上面的声明代码是LruCache中注释文本中的,源码中已经明确的告诉我们使用的方法。
上面的声明只是告诉我们最大可以缓存的值和缓存的元素大小的计算方法。我们也可以不这么用,我们设置最大缓存的元素个数(以下代码不可使用,因为你不知道元素的大小,非常内存泄漏,我写的原因,只是告诉大家这边的值是可以灵活变动的,LruCache的作用只是按照我们给的方式计算):
//lrucache可以存放的最大元素个数,超过这个值就开始remove掉最少使用元素
int cacheSize = 4; // 元素的个数
LruCache
bitmapCache = new LruCache
(cacheSize) {
//这个方法是返回个数
protected int sizeOf(String key, Bitmap value) {
return 1;
}
}}
上面代码只是参考,谢谢。
LruCache的使用:
//lrucache可以存放的最大内存,超过这个值就开始remove掉最少使用元素
int cacheSize = 4 * 1024 * 1024; // 4MiB
LruCache
bitmapCache = new LruCache
(cacheSize) {
//这个方法是返回bitmap的占用内存的大小
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}}
//添加元素
public void setItem(String key,Bitmap bitmap){
cache.put(key, bitmap);
}
//获取元素
public Bitmap getItem(String key){
return cache.get(key);
}
LruCache的声明和使用和简单,要注意的就是关于缓存大小的设置,网上很多都是设置应用程序大小的1/8.这个看你个人情况。下面就开始分析源码:
因为源码太多,所有只是截取了重要的部分:
//核心map,这个就是实现lru的核心,也是我们的分析重点对象
private final LinkedHashMap
map;
//当前元素总的内存大小
private int size;
//我们设置的最大内存
private int maxSize;
//remove掉的元素个数
private int evictionCount;
//命中的次数
private int hitCount;
//没有命中的次数
private int missCount;
//构造函数
public LruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
//初始化map
this.map = new LinkedHashMap
(0, 0.75f, true);
}
public void resize(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
synchronized (this) {
this.maxSize = maxSize;
}
trimToSize(maxSize);
}
//从map中获取元素
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++;
}
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;
}
}
//存放元素
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;
}
//当size>maxsizes,是删除最少使用元素
public void trimToSize(int maxSize) {
while (true) {
K key;
V value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName()
+ ".sizeOf() is reporting inconsistent results!");
}
if (size <= maxSize) {
break;
}
Map.Entry
toEvict = map.eldest();
if (toEvict == null) {
break;
}
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= safeSizeOf(key, value);
evictionCount++;
}
entryRemoved(true, key, value, null);
}
}
//移除指定元素
public final V remove(K key) {
if (key == null) {
throw new NullPointerException("key == null");
}
V previous;
synchronized (this) {
previous = map.remove(key);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}
if (previous != null) {
entryRemoved(false, key, previous, null);
}
return previous;
}
//元素大小(需要覆写)
protected int sizeOf(K key, V value) {
return 1;
}
//移除所有元素
public final void evictAll() {
trimToSize(-1); // -1 will evict 0-sized elements
}
上面是源码中主要的字段和方法,代码不难所有不做太多叙述,重点要讲的就是 map 这个字段。因为lruCache完全是对
LinkedHashMap的封装。
因为LinkedHashMap,HashMap,AbstractMap,Map代码过多,所有我把<<LinkedHashMap源码分析>>,放到一篇新的微博中: