美文网首页
Glide解析五:活跃缓存策略

Glide解析五:活跃缓存策略

作者: jxiang112 | 来源:发表于2019-03-18 15:54 被阅读0次

阅读本篇文章,建议先阅读:
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整体流程中有比较详细的解析说明,大体就是图片从网络上加载之后,放入磁盘,再从磁盘中经过转换之后就会放入活跃缓存中。

相关文章

网友评论

      本文标题:Glide解析五:活跃缓存策略

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