Android缓存机制LruCache

概述
LRU(Least Recently Used)近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。缓存分为两种LrhCache(内存缓存)和DisLruCache(硬盘缓存)。
LruCache的使用

//①设置LruCache缓存的大小,一般为当前进程可用容量的1/8。
//②重写sizeOf方法,计算出要缓存的每张图片的大小。

int maxMemory = (int) (Runtime.getRuntime().totalMemory()/1024);
        int cacheSize = maxMemory/8;
        mMemoryCache = new LruCache(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight()/1024;
            }
        };

HashMap是一种非常常见、非常有用的集合,并且在多线程情况下使用不当会有线程安全问题。而且HashMap线程是无序的。
LinkedHashMap它增加了时间和空间上的开销,通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序。
LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序

Android缓存机制LruCache_第1张图片
image.png

LruCrash 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;
    }

添加过缓存对象后,调用 trimToSize()方法,来判断缓存是否已满,如果满了就要删除近期最少使用的算法。

trimToSize()

 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);
        }
    }

缓存大小大于等于最大值 trimToSize()方法不断地删除LinkedHashMap中队尾的元素。

LruCache的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++;
        }

lru的get()方法调用了LinkedHashMap的get()方法

LinkedHashMap.get()

public V get(Object key) {
        LinkedHashMapEntry e = (LinkedHashMapEntry)getEntry(key);
        if (e == null)
            return null;
        //实现排序的关键方法
        e.recordAccess(this);
        return e.value;
    }

void recordAccess(HashMap m) {
            LinkedHashMap lm = (LinkedHashMap)m;
            //判断是否是访问排序
            if (lm.accessOrder) {
                lm.modCount++;
                //删除此元素
                remove();
                //将此元素移动到队列的头部
                addBefore(lm.header);
            }
        }

你可能感兴趣的:(Android缓存机制LruCache)