我们在做图片加载的时候,都是使用了磁盘缓存或者内存缓存,这是必须必须的,今天就讲下内存缓存,它的里层是怎么实现的,可能比你想象的要简单,
先看下 LruCache几个变量的定义:
private final LinkedHashMap<K, V> map; /** Size of this cache in units. Not necessarily the number of elements. */ private int size; private int maxSize; private int putCount; private int createCount; private int evictionCount; private int hitCount; private int missCount;
它定义了一个LinkedHashMap来维护加载的图片,使用LinkedHashMap集合的好处在于它是有序的,然后看下这个类的构造是什么样的,
/** * @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); }
构造传递的是准备开辟多少内存给加载图片,但是得计算每个图片所占的内存大小啊,不然到时候怎么知道加载图片的总数内存和你分配的内存做比较,
/** * Returns the size of the entry for {@code key} and {@code value} in * user-defined units. The default implementation returns 1 so that size * is the number of entries and max size is the maximum number of entries. * * <p>An entry's size must not change while it is in the cache. */ protected int sizeOf(K key, V value) { return 1; }
在创建对象的时候重写这个方法就可以了,然后就是看put方法了,
/** * Caches {@code value} for {@code key}. The value is moved to the head of * the queue. * * @return the previous value mapped by {@code key}. */ public final V put(K key, V value) { if (key == null || value == null) {//对传递进来的K,V进行容错判断 throw new NullPointerException("key == null || value == null"); } V previous;//临时保存V值,一般都是Bitmap synchronized (this) {// putCount++;//计算图片的数量 size += safeSizeOf(key, value);//计算图片所占内存大小 size是积累所有加载图片所占内存的大小 previous = map.put(key, value); if (previous != null) {//判断这个之前内存加载过,如果加载过了,内存就不应该把刚之前算的内存所占大小加进去 size -= safeSizeOf(key, previous); } } if (previous != null) { entryRemoved(false, key, previous, value);// } trimToSize(maxSize); return previous; }
晚上写