Glide解析五:活跃缓存策略

阅读本篇文章,建议先阅读:
Glide解析一:Glide整体流程
在分析Glide的整体流程时,我们知道Glide有三级缓存策略,一个是活跃内存缓存,一个是内存缓存,一个是磁盘缓存。这边文章将对活跃内存缓存策略进行剖析。
在Glide整体流程分析知道ActiveResources的活跃内存缓存的实现,我们从这个类进行入手:
ActiveResources的核心就是维护一个Map,这个map就是维系图片包装类弱引用的:

final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();

ResourceWeakReference继承了WeakReference:

static final class ResourceWeakReference extends WeakReference<EngineResource<?>> {
     //关联的key
    @SuppressWarnings("WeakerAccess") @Synthetic final Key key;
    //是否可缓存
    @SuppressWarnings("WeakerAccess") @Synthetic final boolean isCacheable;
    //关联的图片资源
    @Nullable @SuppressWarnings("WeakerAccess") @Synthetic Resource<?> resource;

    @Synthetic
    @SuppressWarnings("WeakerAccess")
    ResourceWeakReference(
        @NonNull Key key,
        @NonNull EngineResource<?> referent,
        @NonNull ReferenceQueue<? super EngineResource<?>> queue,
        boolean isActiveResourceRetentionAllowed) {
      super(referent, queue);
      this.key = Preconditions.checkNotNull(key);
      this.resource =
          referent.isCacheable() && isActiveResourceRetentionAllowed
              ? Preconditions.checkNotNull(referent.getResource()) : null;
      isCacheable = referent.isCacheable();
    }

    void reset() {
      resource = null;
      //清除ResourceWeakReference 
      clear();
    }
  }

既然是维系Map,那么从活跃缓存中取图片资源对应的就是get,将图片资源加入活跃缓存中对于的就是put。
我们先看下put的操作:

void activate(Key key, EngineResource<?> resource) {
    //将图片资源和关联的key使用弱引用进行包装s关联
    ResourceWeakReference toPut =
        new ResourceWeakReference(
            key,
            resource,
            getReferenceQueue(),
            isActiveResourceRetentionAllowed);
    //将包装之后的图片资源弱引用加入map中
    ResourceWeakReference removed = activeEngineResources.put(key, toPut);
    if (removed != null) {
      //移除之前就的图片资源弱引用
      removed.reset();
    }
  }

put的操作没什么,就不废话了,代码中有注释说明
get操作:

EngineResource<?> get(Key key) {
    //根据key从map中取出图片资源弱引用
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    if (activeRef == null) {
      //如果图片资源资源弱引用为空,返回空
      return null;
    }
    //从弱引用中获取图片资源
    EngineResource<?> active = activeRef.get();
    if (active == null) {
      //如果图片资源已经释放,则调用cleanupActiveReference清除处理
      cleanupActiveReference(activeRef);
    }
    //返回图片资源
    return active;
  }

get的操作其实就是从map取出弱引用对象,再从弱引用对象中取出图片资源。这里有个关键的地方cleanupActiveReference,如果配置的图片可缓存,那么这里就会将活跃缓存中的图片资源移除到内存缓存中,我们看下cleanupActiveReference的系列逻辑:

@Synthetic void cleanupActiveReference(@NonNull ResourceWeakReference ref) {
    //断言是否在主线程,如果不在主线程则抛出异常
    Util.assertMainThread();
    //从map中移除key对应的图片资源弱引用对象
    activeEngineResources.remove(ref.key);

    if (!ref.isCacheable || ref.resource == null) {
      //如果图片不可缓存或者图片资源为空,则结束
      return;
    }
    //图片可缓存并且图片资源不为空
   //重新包装成EngineResource图片资源对象
    EngineResource<?> newResource =
        new EngineResource<>(ref.resource, /*isCacheable=*/ true, /*isRecyclable=*/ false);
    newResource.setResourceListener(ref.key, listener);
    //回调告知图片资源已经从活跃缓存中移除释放
    listener.onResourceReleased(ref.key, newResource);
  }

这里的listener就是图片加载引擎Engine对象,我们看下图片加载引擎Engine对象的onResourceReleased方法是做什么处理的:

public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
    //断言是否在主线程,如果不在主线程则抛出异常
    Util.assertMainThread();
    //从活跃缓存中移除指定key对应的图片资源
    activeResources.deactivate(cacheKey);
    if (resource.isCacheable()) {
      //图片资源可缓存
      //将活跃缓存移除的图片资源加入内存缓存中进行缓存
      cache.put(cacheKey, resource);
    } else {
      //图片资源不可缓存,执行释放操作
      resourceRecycler.recycle(resource);
    }
  }

void deactivate(Key key) {
    //从map中删除key对应的图片资源弱引用
    ResourceWeakReference removed = activeEngineResources.remove(key);
    if (removed != null) {
      //清除释放图片资源弱引用
      removed.reset();
    }
  }

综合上述解析,其实活跃缓存策略没什么复杂的,它的核心:

  • 使用弱引用对图片资源和key进行包装
  • 用HashMap进行管理,key是与图片资源关联的Key,value是经过包装的图片资源弱引用
  • put操作就是讲图片资源包装成图片资源弱引用对象,然后放入HashMap中
  • get操作就是根据key从HashMap中取出对应的图片资源弱引用对象,再从图片资源弱引用对象中取出图片资源,当弱引用中图片资源为空,如果可缓存则将图片资源缓存到内存缓存中,否则进行回收释放操作

那么什么时候图片会加入活跃缓存中的呢?Glide解析一:Glide整体流程中有比较详细的解析说明,大体就是图片从网络上加载之后,放入磁盘,再从磁盘中经过转换之后就会放入活跃缓存中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

  • 7.1 压缩图片 一、基础知识 1、图片的格式 jpg:最常见的图片格式。色彩还原度比较好,可以支持适当压缩后保持...
    AndroidMaster阅读 2,479评论 0 13
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32
  • 上篇我们以加载一张网络图片为例,讲解了Glide加载一张图片的整体流程。为了更连贯的理解流程我们略过了一些细节,包...
    嘎啦果安卓兽阅读 50,332评论 7 46
  • 一、简介 在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫Glide的图片加载库,作者是bumptech。这...
    天天大保建阅读 7,447评论 2 28
  • 蹲在地上剥花生的时候,突然想起我们小时候,外婆给我们在灶塘里焙花生的情景来。 奶奶在父亲年幼时就已经去世了,外婆家...
    胖鱼_2282阅读 425评论 0 2