Picasso 图片加载库源码分析3-内存缓存

2021-07-02  本文已影响0人  jkwen

前面说的 OkHttp3Downloader 其实可以理解为磁盘缓存,缓存算法用的是 LRU,这里说的是内存缓存,同样缓存算法用的也是 LRU。

创建 LurCache 对象需要提供缓存大小,这个大小其实跟应用配置有关(即 largeHeap 相关的配置),如果没有配置,默认将是 16 MB 的 15% 左右。

public LruCache(int maxByteCount) {
    cache = new android.util.LruCache<String, LruCache.BitmapAndSize>(maxByteCount) {
        @Override protected int sizeOf(String key, BitmapAndSize value) {
        return value.byteCount;
      }
    };
}

最后通过该构造方法,创建了一个 Android 自带的 LruCache 类型对象。android.util 包下的这个 LruCache 类型是个泛型类,有点类似 Map,不过其内部本质还真用到了 LinkedHashMap 来维护,从代码上可以知道这个 LruCache 以 String 类型为 key,BitmapAndSize 类型为 value。这个 BitmapAndSize 类型是 picasso 包下面的 LruCache 类里的静态类,内容就像名字一样一个属性是 Bitmap,一个属性是 byteCount。

LRU 算法

插播一个概念介绍 什么是LRU(最近最少使用)算法? 网上一搜一大堆,我觉得这篇理解起来简单,所以引用了。

有了 LRU 概念之后就知道 android.util 包下的 LruCache 实现为什么用到 LinkedHashMap 了。再来看下 Picasso 的 LruCache 几个方法实现,

set

public void set(@NonNull String key, @NonNull Bitmap bitmap) {
    int byteCount = Utils.getBitmapBytes(bitmap);
    //首先做了一个图片大小的判断
    //如果单张图片超过了缓存空间大小,那就不考虑缓存了,
    //顺带把缓存里相同的这个 key 的缓存也移除
    if (byteCount > maxSize()) {
        cache.remove(key);
        return;
    }
    //通过大小检测后就往里放
    cache.put(key, new BitmapAndSize(bitmap, byteCount));
}

至于 android.util 包下的 LruCache 的 put 方法逻辑大致是这样的,1.获取将要缓存的资源大小求的当前已缓存的大小,并放入 LinkedHashMap 中,如果 Map 中有相同的 key 值,就会把之前所占的大小减掉。2.重新比对已缓存大小是否超过设定的最大值,如超过,则从 Map 最后一位开始移除,从而腾出一些空间。但感觉这里并没有体现出 LRU 的实现,这个还有待测试验证。

get

@Override public Bitmap get(@NonNull String key) {
    //get 方法很简单,通过 key 从 Map 里获取对应 value
    //有就返回图片对象,没有就没有了。
    BitmapAndSize bitmapAndSize = cache.get(key);
    return bitmapAndSize != null ? bitmapAndSize.bitmap : null;
}

还有其他几个方法,

上一篇 下一篇

猜你喜欢

热点阅读