Android图片框架Glide学习记录和总结

415 阅读4分钟

本文主要做Glide的学习记录和总结,无原理和源分析析。

Glide 缓存分为内存缓存硬盘缓存(DiskLruCache),内存缓存又分Lru算法缓存(LruResourceCache)和弱引用缓存(ActiveResources)。

弱引用

弱引用(Weak Reference):弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

判断弱引用对象的关键在于只具有弱引用的对象,也就是说,如果一个对象有强引用,那么在系统GC时,是不会回收此对象的,也不会释放弱引用。JDK中使用弱引用的代表是ThreadLocal,内存泄漏监听工具LeakCannary也是使用弱引用的原理。

引用队列

WeakReference类有两个构造函数:

//创建一个指向给定对象的弱引用
WeakReference(T referen);
//创建一个指向给定对象并且登记到给定引用队列的弱引用
WeakReference(T referent, ReferenceQueue<? super T> q);

我们可以看到第二个构造方法中提供了一个ReferenceQueue类型的参数,通过提供这个参数,我们便把创建的弱引用对象关联到了一个引用队列上,当它被垃圾回收器清除时,就会把它送入这个引用队列中,我们便可以对这些被清除的弱引用对象进行统一管理。

Glide 获取资源顺序

graph TD
弱引用缓存 --> Lru缓存 --> 读取文件/网络

Glide 加载资源入口在Engine#load()方法,里面会调Engine#loadFromMemory()方法从内存中取出资源,Engine#loadFromMemory()里又分别调用了Engine#loadFromActiveResources()Engine#loadFromCache()

@Nullable
private EngineResource<?> loadFromMemory(
    EngineKey key, boolean isMemoryCacheable, long startTime) {
  if (!isMemoryCacheable) {
    return null;
  }

  EngineResource<?> active = loadFromActiveResources(key);
  if (active != null) {
    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Loaded resource from active resources", startTime, key);
    }
    return active;
  }

  EngineResource<?> cached = loadFromCache(key);
  if (cached != null) {
    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Loaded resource from cache", startTime, key);
    }
    return cached;
  }

  return null;
}

ActiveResources内使用HashMap保存资源,MapVlaueWeakReference弱引用对像,并且在创建弱引用时关联ReferenceQueue引用队列,如果资源被gc回收,JVM会把弱引用对像添加到引用队列中。
ActiveResources内使使用使用线程池创建子线程并不断循环调用WeakReference#remove方法监听是否有资源被回收,如果资源被回收,从HashMap中移除弱引用。

WeakReference#remove()方法是阻塞方法,并且是线程安全的。

Glide 的一些策略

  1. 从网络或磁盘中加载资源时会加入弱引用缓存。
  2. 如果在Lru缓存中找到资源,把资源从Lru缓存中移除,并存入弱引用缓存中。
  3. 引用缓存监听到资源被gc回收,资源从弱引用缓存移除,并加入LruCache。

Glide 的一些总结

  1. Glide内存缓存为什么使用 activeResources 和 LruCahce?
    activeResources旨在提高图片的加载速度以及防止 LruCache 误删使用中的图片。 LruCache旨在提高想要使用的图片的精准度以及减少IO操作,提高性能。
  2. Glide为什么在获取 LruCache 缓存的图片时使用 remove ?
    LruCahce使用 LinkedHashMap(双向链表+散列表)管理图片资源,目的是在有限的内存中,尽可能的缓存会被使用的数据。它对每个图片使用的是强引用。 由于我们使用了 activeResource ,它使用弱引用管理正在使用的图片资源,所以我们只需要在弱引用释放的时候在把数据放回 LruCache 中,就可以了。性能更好。
  3. Glide 使用的缓存策略是什么?
    Glide 使用了三级缓存,首先从内存中查找数据,没有命中,则从磁盘缓存中获取文件数据,再没有命中,则发起请求获取图片。另外,内存缓存使用了两个策略:1. 先从 activeResources 中查找弱引用持有的图片,没有命中,则从 LruCahce 中获取强引用持有的图片。磁盘缓存使用的依然是 LruCahce算法,至于网络使用了 okhttp。
  4. Glide 将图片写入内存缓存的时机:
    图片加载完成后 、图片显示出来前
  5. Glide将图片写入 磁盘缓存的时机:
    获取图片资源后 、图片加载完成前

其它

Glide 还使用了LruBitmapPool缓存,下次再研究。