Glide 源码解析 之 内存缓存

765 阅读2分钟

注:为了突出重点,文中的源码有大量删节,有的用//..进行了标识,有的没有。

引子

图片加载

Engine#load()

  public <R> LoadStatus load(//..) {
    //..
    // 一级内存缓存
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      //..
      return null;
    }
    // 二级内存内存
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      //..
      return null;
    }
    //..
  }

ActiveResources解析

获取 ActiveResource 缓存

Engine#loadFromActiveResources()

  private final ActiveResources activeResources;
  
  @Nullable
  private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
    //..
    EngineResource<?> active = activeResources.get(key);
    //..
    return active;
  }

ActiveResource

本质是一个HashMap,用WeekReference保存EngineResource,用作内存缓存。

final class ActiveResources {
  final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
    
  static final class ResourceWeakReference extends WeakReference<EngineResource<?>> {
    //..
  }
  
  void activate(Key key, EngineResource<?> resource) {
    ResourceWeakReference toPut = new ResourceWeakReference(//..)
    ResourceWeakReference removed = activeEngineResources.put(key, toPut);
    //..
  }
    
  void deactivate(Key key) {
    ResourceWeakReference removed = activeEngineResources.remove(key);
    if (removed != null) {
      removed.reset();
    }
  }
  
    
  EngineResource<?> get(Key key) {
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    //..
    return active;
  }
}

ActiveResources 缓存的添加和移除

从调用关系可以看到activate是在EngineJobCompleteloadFromcache时调用的,deactivate是在onResourceRelease时调用的。调用都是在Engine中,可见ActiveResources的维护都是有Engine维护的。

Usages of ActiveResources#activate

Usages of ActiveResources#deactivate

MemoryCache 解析

获取 MemoryCache 缓存

Engine#loadFromCache

  private final MemoryCache cache;
  private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
    //..
    EngineResource<?> cached = getEngineResourceFromCache(key);
    //..
    return cached;
  }
  
  private EngineResource<?> getEngineResourceFromCache(Key key) {
    Resource<?> cached = cache.remove(key);
    //..
    return result;
  }

MemoryCache 的具体实现

MemoryCache 是一个接口, 默认的实现是LruResourceCache。 初始化逻辑: GlideBuilder#build

  @NonNull
  Glide build(@NonNull Context context) {
    //..
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
            //..);
    }
    //..
  }

LruResourceCache 的继承结构

LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache

MemoryCache 缓存的添加和移除

加入是在onResourceReleased,联系前面的源码只可以看到,在onResourceReleased中cache从ActiveResource中移出来,放到LruResourceCache中了。
移出是在getEngineResourceFromCache()中,从LruResourceCache移到ActiveResource中,刚好对应。

再来回顾一下Glide内存缓存的逻辑 onEngineJobComplete 图片被缓存到ActiveResources onResourceReleased 图片从ActiveResources移到LruResourceCache loadFromCache 图片从LruResourceCache移到ActiveResources

  @Override
  public void onEngineJobComplete(EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
    //..
     if (resource.isCacheable()) {
        activeResources.activate(key, resource);
    }
  }
  
  @Override
  public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
    activeResources.deactivate(cacheKey);
    //..
    cache.put(cacheKey, resource);
    //..
  }
  
  private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
    //..
    EngineResource<?> cached = getEngineResourceFromCache(key);
    activeResources.activate(key, cached);
    return cached;
  }
  
  private EngineResource<?> getEngineResourceFromCache(Key key) {
    Resource<?> cached = cache.remove(key);
    //..
  }

回顾Engine、ActivityResources、LruCacheResourceCache

从上面的分析可以看到,cache的加入和移除都是通过Engine的回调方法进行处理的,也就是说Engine监听图片加载过程中的各种事件,在事件发生的时候采取相应的行动维护缓存。Engine实现了3个interface,一个这对图片加载任务,一个针对ActiveResources,一个针对LruCacheResourceCache,结构非常清晰。

public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener{}
    
interface EngineJobListener {
  void onEngineJobComplete(EngineJob<?> engineJob, Key key, EngineResource<?> resource);

  void onEngineJobCancelled(EngineJob<?> engineJob, Key key);
}

MemoryCache
interface ResourceRemovedListener {
  void onResourceRemoved(@NonNull Resource<?> removed);
}

EngineResource
interface ResourceListener {
  void onResourceReleased(Key key, EngineResource<?> resource);
}