美文网首页
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