Android的缓存方法有内存缓存和磁盘缓存,像一些实时的图片展示一般都是用内存缓存的,例如微博、朋友圈的图片;而一些相对固定的图片数据比如有些客户端的图片资源需要从网上下载然后存到磁盘中,以后每次启动只需从缓存中获取即可。今天就来探究一下内存缓存的实现及其原理。
Android的内存缓存使用LruCache类实现,如果容器已满,就使用LRU置换算法替换掉某个数据。什么是LRU置换算法呢?
LRU(Least Recently Used)中文为最近最久未使用算法,当容器满时选择最近最久没被使用的数据予以淘汰。该算法赋予每个数据一个访问字段,用来记录一个数据自上次被访问以来所经历的时间t,当须淘汰一个数据时,选择现有数据中其t值最大的,即最近最久未使用的数据予以淘汰。这种算法在系统的内存页面置换也有用到。
先来看看v4包中的LruCache这个类
private final LinkedHashMap<K, V> map;
/**
* @param maxSize for caches that do not override {@link #sizeOf}, this is
* the maximum number of entries in the cache. For all other caches,
* this is the maximum sum of the sizes of the entries in this cache.
*/
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来保存键值对,达到缓存的目的。并且构造方法上的注释写得很清楚,分析HashMap的源码也可知,默认情况下maxSize是保存的键值对的个数,每次put键值对进来的时候会调用trimToSize(maxSize)来判断是否超出了最大值,如果超出了则移除最近最久未被使用的元素。
看看put方法:
public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}