LRUCache源码解析

本文详细解析了LRUCache的源码,包括构造方法、sizeOf方法用于计算缓存大小、put方法用于存储数据并遵循LRU策略、get方法进行安全的线程同步获取缓存以及safeSizeOf方法用于调整缓存容量。LRUCache借助LinkedHashMap实现,通过自定义sizeOf方法确保每个Bitmap的大小计算,并在缓存满时淘汰最近最少使用的条目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LruCache源码解析

LruCache通常用来做图片缓存,通过LRU算法来缓存图片,我们来看源码是怎么实现!

构造方法

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

LruCache内部使用了一个LinkedHashMap来保存数据,LinkedHashMap的3个参数:

    public LinkedHashMap(int initialCapacity,
                     float loadFactor,
                     boolean accessOrder) {
    super(initialCapacity, loadFactor);
    this.accessOrder = accessOrder;
}   
initialCapacity:初始容量
loadFactor:不知道有什么用,载入因素,可以理解为时间,空间上性能的一个参数!
accessOrder:这个参数是用来实现LRU算法的!    

sizeOf

通过复写sizeOf方法,我们可以指定每个Bitmap实体的大小

 mCache = new LruCache<String, Bitmap>(maxSize) {
        @SuppressLint("NewApi")
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            return bitmap.getByteCount();
        }
    };

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

这里的代码思路很简单,就是key,value建值对放到LinkedHashMap中,LinkedHashMap负责将其放到首个位置,
然后移除旧的缓存!

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

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

get方法首先从map中去除缓存,如果存在就返回,由于LinkedHashMap是线程不安全的,所以加上synchronized关键字!
如果没有命中,通过create去创建:

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

create默认是空实现,如果不实现这个方法,就不会对create生成的值进行存储,接下来:

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

synchronized代码块里面,将创建createdValue加入到缓存中,返回旧的mapValue,如果有其他线程已经put了一个key,value,就将mapValue最为命中的缓存,而不使用createdValue!
其实后面的逻辑一般来说用不到,因为我们在缓存取不到的时候就直接做其他操作了,比如网络加载,或者显示默认图片!

safeSizeOf

后面的safeSizeOf用来计算bitmap的大小,然后重置整个缓存的容量大小的!

整个LRUCache源码实现大概就是这样!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值