LruCache

原文地址:https://hexige.github.io/blog/2017/07/24/LruCache/

谷歌官方建议使用LruCache(least recentlly use 最近最少使用算法)来保存Bitmap对象;

使用

private static int MAX_SIZE = (int)(Runtime.getRuntime().maxMemory()/8);
LruCache mBitmapCache = new LruCache<>(MAX_SIZE);

源码

LruCache在内部维护了一个LinkedHashMap,也就是使用了LinkedHashMap的Lru调度算法。

在构造方法中:

  • 初始化了cache的大小;
  • 初始化LinkedHashMap,accessOrder为true,即为Lru调度方式;
public LruCache(int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0");
        }
        this.maxSize = maxSize;
        this.map = new LinkedHashMap(0, 0.75f, true);
    }

get方法:通过key获取相应的value,或者返回创建新的value。
同时此记录会移至队列的尾部;

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.
         */

        //create()方法默认为空实现,如需在未获得value时创建新的对象,则可重写此方法;
        V createdValue = create(key);
        if (createdValue == null) {
            return null;
        }
        
        //如果新创建了对象
        synchronized (this) {
            createCount++;
            //将createdValue放入map中,同时将原来key对应的value保存到mapValue中
            mapValue = map.put(key, createdValue);

            if (mapValue != null) {
                // There was a conflict so undo that last put
                //mapValue不为空则撤销上一步操作
                map.put(key, mapValue);
            } else {
                //加入新的对象后,重新计算size
                size += safeSizeOf(key, createdValue);
            }
        }

        if (mapValue != null) {
            entryRemoved(false, key, createdValue, mapValue);
            return mapValue;
        } else {
            //每次加入新对象,都会调用trimToSize方法查看时候需要回收
            trimToSize(maxSize);
            return createdValue;
        }
    }

trimToSize():根据maxSize来调整cache的大小

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!");
                }
                //如果当前size小于maxSize,break
                if (size <= maxSize) {
                    break;
                }
                //如果当前链表头部元素为null,break
                Map.Entry toEvict = map.eldest();
                if (toEvict == null) {
                    break;
                }

                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                //回收次数+1
                evictionCount++;
            }

            entryRemoved(true, key, value, null);
        }
    }

你可能感兴趣的:(LruCache)