LruCache

LruCache

Android api 12 新增类,support v4 有向前兼容的版本。

构造方法


    /**
     * @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);
    }

接收传入的最大缓存数并实例化一个初始空间为0,负载因子0.75,迭代顺序为访问顺序的LinkedHashMap。

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

LruCache 的key、value 都不能为空。safeSizeOf() 方法默认返回1,previous 为key 之前所绑定的值,若存在,则size减去被替换value的大小,原有值被替换删除,可重写entryRemoved()自行处理,默认空实现.trimToSize(),清理至maxSize。

get()

  /**
     * Returns the value for {@code key} if it exists in the cache or can be
     * created by {@code #create}. If a value was returned, it is moved to the
     * head of the queue. This returns null if a value is not cached and cannot
     * be created.
     */
    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.
         */

        V createdValue = create(key);
        if (createdValue == null) {
            return null;
        }

        synchronized (this) {
            createCount++;
            mapValue = map.put(key, createdValue);

            if (mapValue != null) {
                // There was a conflict so undo that last put
                map.put(key, mapValue);
            } else {
                size += safeSizeOf(key, createdValue);
            }
        }

        if (mapValue != null) {
            entryRemoved(false, key, createdValue, mapValue);
            return mapValue;
        } else {
            trimToSize(maxSize);
            return createdValue;
        }
    }

存在此key,返回value 并移动到队列头部;不存在时,可创建,[create](#create(key)默认返回null,若创建成功,后续类似put操作。

sizeOf()

  /**
     * 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;
    }

entryRemoved()

    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}

create(key)

  protected V create(K key) {
        return null;
    }

trimToSize()

    /**
     * Remove the eldest entries until the total of remaining entries is at or
     * below the requested size.
     *
     * @param maxSize the maximum size of the cache before returning. May be -1
     *            to evict even 0-sized elements.
     */
    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 || map.isEmpty()) {
                    break;
                }

                Map.Entry<K, V> toEvict = map.entrySet().iterator().next();
                key = toEvict.getKey();
                value = toEvict.getValue();
                map.remove(key);
                size -= safeSizeOf(key, value);
                evictionCount++;
            }

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

缓存数超过maxSize时,清理多的数据,从最老的开始。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • https://developer.android.google.cn/topic/performance/gra...
    十二书阅读 3,210评论 0 4
  • 讲到LruCache不得不提一下LinkedHashMap,因为LruCache中Lru算法的实现就是通过L...
    小宏why阅读 1,037评论 1 1
  • LruCache LruCache是Android3.1提供的缓存类,并且在v4包提供了该类。LruCache是一...
    Cris_Ma阅读 3,004评论 0 1
  • 蔡澜是我很喜欢的一个作家,从很久之前在一次书店随手拿起的一本旧书里认识了他,就一发不可收拾,痴迷吗?那倒似乎还不是...
    筱念凉阅读 484评论 6 6
  • 回忆裹藏污泥,被虚伪一遍遍翻起,直到血管里充满浑浊的液体。 人们大多无恶意,也许只是突然想起,或刚好忘记,惊异于自...
    瞎子的世界阅读 210评论 0 1