LruCache原理解析--基于Android api28

2020-02-27  本文已影响0人  郑土强ztq

简介

基本原理

LruCache中有个LinkedHashMap类型的成员变量map,在LruCache的构造函数中将会初始化map变量。map=new LinkedHashMap(0,0.75f,true),实例化了一个以访问顺序来排序元素的LinkedHashMap对象。LruCache只是加上了控制缓存大小的逻辑,实际上数据是由LinkedHashMap保存的。

最近最少使用的特性是如何实现的?

由LinkedHashMap保证此特性,在实例化LinkedHashMap时指定accessOrder参数为true。调用LinkedHashMap的put或者get函数都会把该元素插入(或者移动)到序列的尾部。LruCache每次put的时候会检查当前的大小是否超过了限制,是的话就会调用trimToSize去把最近最少使用的元素淘汰掉。

trimToSize(int maxSize)

private 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) {//1.
                    break;
                }

                // BEGIN LAYOUTLIB CHANGE
                // get the last item in the linked list.
                // This is not efficient, the goal here is to minimize the changes
                // compared to the platform version.
                Map.Entry<K, V> toEvict = null;
                for (Map.Entry<K, V> entry : map.entrySet()) {
                    toEvict = entry;
                }
                // END LAYOUTLIB CHANGE

                if (toEvict == null) {//2.
                    break;
                }

                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }

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

trimToSize是个死循环,以下两种情况会退出循环:

  1. 当前的容量size<maxSize;

  2. LruCache中没有元素。

这个函数是实现LruCache元素数量限制的关键。它会把LinkedHashMap的尾部数据,即不“活跃”的数据,remove掉,从而来实现元素数量限制的特性。

上一篇下一篇

猜你喜欢

热点阅读