美文网首页
LruCache源码分析

LruCache源码分析

作者: 鲁班0号 | 来源:发表于2019-05-12 23:17 被阅读0次

LruCache代码只有300多行,看起来很简单

0. 属性

//主要的存储成员变量
private final LinkedHashMap<K, V> map;
//当前容量
private int size;
//最大的值
private int maxSize;
//put的次数 
private int putCount;
//create的次数 
private int createCount;
//回收次数
private int evictionCount;
//命中次数
private int hitCount;
//丢失的次数
private int missCount;

关于LinkedHashMap,我们已经讲过了,这里就不再叙述了

1. 方法

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);
    }
  • initialCapacity 用于初始化该 LinkedHashMap 的大小。
  • loadFactor(负载因子)这个LinkedHashMap的父类 HashMap 里的构造参数,涉及到扩容问题,比如 HashMap 的最大容量是100,那么这里设置0.75f的话,到75的时候就会扩容。
  • accessOrder,这个参数是排序模式,true表示在访问的时候进行排序( LruCache 核心工作原理就在此),false表示在插入的时才排序。

1.1 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++;
            //如果部重写,那么这个容量就是1
            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;
    }

1.2 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<K, V> 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);
        }
    }

该方法就是循环查找如果当前的大小超过最大的值,那么就删除最旧的节点,回收次数+1,直到size小于maxSize为止。

1.3 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++;
        }
        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;
        }
    }

get方法流程是:

  1. 根据key从map中拿数据,如果拿到数据那么就命中次数+1,然后退出;
  2. 如果没有拿到map中数据,那么miss+1,然后创建value,LruCache中数据是null,所以会直接返回null;
  3. 如果子类重写了create的方法,那么createCount++,并且以这个key保存到map中,如果map中存在了key,那么重新put上一次的value,如果不为空,那么size变大。

LruCahe先分析到这里!

相关文章

  • Android-Glide源码解析

    一、LruCache 要分析Glide的源码,首先就需要分析LruCache。LruCache是基于LinkedH...

  • LruCache之LruCache分析

    LruCache 分析 LruCache 是 Android 的一个内部类,提供了基于内存实现的缓存 用法 源码 ...

  • LruCache

    文章主要介绍了:1.LruCache的基本使用2.LruCache的源码分析3.基于LinkedHashMap的实...

  • LruCache源码分析

    LruCache类里面有一个LinkedHashMap map的变量,缓存主要就是用这个map来做的,l...

  • 源码分析 LruCache

    简介 为什么用 一个app持有的内存是有限的,无限制的使用强引用在内存中缓存数据,有可能导致OOM。 能做什么 L...

  • LruCache源码分析

    在开发中我们会经常碰到一些资源需要做缓存优化,例如Bitmap,Json等,那么今天我们来瞧瞧默默无闻的LruCa...

  • LruCache源码分析

    LruCache的原理 LruCache主要靠LinkedHashMap的一个按访问排序的特性实现的,Linked...

  • LruCache源码分析

    LruCache的源码分析已经很多了,看了很多遍,但是自己走一遍分析,才是真正的掌握,将知识转化到自身。 用途 L...

  • LruCache源码分析

    LruCache的源码分析已经很多了,看了很多遍,但是自己走一遍分析,才是真正的掌握,将知识转化到自身。 用途 L...

  • LruCache源码分析

    对于LruCache的分析,我们可以从官方介绍开始,直接把源码中的注释拿过来。 A cache that hold...

网友评论

      本文标题:LruCache源码分析

      本文链接:https://www.haomeiwen.com/subject/navcoqtx.html