Glide 4.12图片框架之多级缓存源码设计分析

一、Glide缓存初识

在上两篇文章中,我们从源码角度分析Glide框架加载图片的流程、以及Glide图片通过巧妙的空view的Fragment的设计实现的Glide的图片加载的三大生命周期函数onStart、onStop、onDestroy。Glide的框架的源码量确实比较大,今天我们再详细分析一下,Glide的框架的缓存模块的设计。

默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存:

  1. 活动资源 (Active Resources) - 现在是否有另一个 View 正在展示这张图片?
  2. 内存缓存 (Memory cache) - 该图片是否最近被加载过并仍存在于内存中?
  3. 资源类型(Resource) - 该图片是否之前曾被解码、转换并写入过磁盘缓存?
  4. 数据来源 (Data) - 构建这个图片的资源是否之前曾被写入过文件缓存?

前两步检查图片是否在内存中,如果是则直接返回图片。后两步则检查图片是否在磁盘上,以便快速但异步地返回图片。

如果四个步骤都未能找到图片,则Glide会返回到原始资源以取回数据(原始文件,Uri, Url等)。

上述这段描述来源于官方文档对于缓存的介绍。官方文档的介绍,已经很清晰的说明了Glide框架在缓存实现的策略。缓存的类型在这里被分为了四类:活动资源、内存缓存、资源类型(磁盘缓存)、数据来源(文件缓存)。

其中活动资源、内存缓存 均属于内存缓存范畴、资源类型、数据来源 均属于磁盘缓存范畴。接下来,我们就从源码角度,来看一下这四级缓存的实现。

二、四级缓存实现的源码分析

结合之前的两篇Glide的分析的文章,我们确认缓存的分析的入口方法为Engine.load的方法,接下来我们就直接再次查看Engine类的相关源码实现:

2.1 活动资源的获取和添加
/** Engine类的功能:对启动的一个加载做响应和管理者活动资源和缓存资源 */
public class Engine imp... {
   
     public <R> LoadStatus load(...) {
   
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
    //key的创建,一份资源(比如图片)的唯一标识
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
   
      //从内存中获取资源
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
      //memoryResource=null,表示活动资源、内存缓存均未获取到
      if (memoryResource == null) {
   
        //等待已经存在或者启动一个新的job
        return waitForExistingOrStartNewJob(
            ....);
      }
    }
  //从内存中获取资源
  private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
   
    //是否启动内存缓存,构建glide的时候可以配置,无的的则直接返回空
    if (!isMemoryCacheable) {
   
      return null;
    }
    //根据key从活动资源中获取
    EngineResource<?> active = loadFromActiveResources(key);
    //活动资源不为空
    if (active != null) {
   
      //将活动资源返回
      return active;
    }
    //活动资源为空,从cache中获取
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
   
      //cache资源不为空,将cache资源返回
      return cached;
    }
    //活动资源和cache资源都为空,则最终返回null
    return null;
  }
}

从上述源码中,主要看loadFromMemory()方法的实现,流程上,先从活动内存获取缓存,如果获取到直接向上层返回,如果获取不到从cache缓存中获取,如果获取到将cache缓存返回,获取不到则返回空。接下来分别具体看活动缓存和cache缓存的究竟:

private final ActiveResources activeResources;
@Nullable
private EngineResource<?> loadFromActiveResources(Key key) {
   
  EngineResource<?> active = activeResources.get(key);
  if (active != null) {
   
    //这个方法是在引擎的resource中定义的,做引用计数
    active.acquire();
  }

  return active;
}
/**
 * 资源包装器
 */
class EngineResource<Z> implements Resource<Z> {
   
//获得引用数
synchronized void acquire() {
   
    if (isRecycled) {
   
      throw new IllegalStateException("Cannot acquire a recycled resource");
    }
    //获得活动资源引用数+1
    ++acquired;
  }
  
//释放引用数
void release() {
   
      boolean release = false;
      synchronized (this) {
   
        if (acquired <= 0) {
   
          throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
        }
        if (--acquired == 0) {
   
          release = true;
        }
      }
      if (release) {
   
        //从活动缓存中释放、迁入cache缓存中
        listener.onResourceReleased(key, this);
      }
    }     
}
@Override
public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
   
  activeResources.deactivate(cacheKey);
  if (resource.isMemoryCacheable()) {
   
    //迁入cache缓存
    cache.put(cacheKey, resource);
  } else {
   
    resourceRecycler.recycle(resource, /*forceNextFrame=*/ false);
  }
}

活动资源是谁来维护的,我们可以看到activeResources.get(key),ActivityResources是活动资源的维护对象,ActivityResources是啥你,追踪一下源码:

final class ActiveResources {
   
  private final boolean isActiveResourceRetentionAllowed;
  private final Executor monitorClearedResourcesExecutor;
  //value 为弱引用对象Map集合
  @VisibleForTesting final Map<
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hymKing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值