提问Glide - 缓存篇

都知道Glide有内存和磁盘缓存,它们的作用和读写场景是什么?

ActiveResources :HashMap + WeakReference

  • 如果当前对应的图片资源正在使用,则这个图片会被Glide放入活动缓存。

  • 读取:Engine.loadFromActiveResources(key) 优先读取ActiveResource缓存。

  • 写入:onEngineJobComplete(磁盘或原数据加载完成)、loadFromMemoryCache(从内存读取并移除然后写入ActiveResources)

  • 剔除:内存不足GC导致系统回收、EngineResource‘引用计数’为0时。

MemoryCache

  • 如果图片最近被加载过,并且当前没有使用这个图片,则会被放入内存中。

  • 读取:Engine.loadFromCache(key) , 在活动资源缓存没命中的前提下尝试读取内存缓存。

  • 写入:EngineResource.release()至引用数为0、ActiveResources被GC回收后。

  • 剔除:LRU算法规则。

ResourceCache

  • 被解码后的图片写入磁盘文件中,解码的过程可能修改了图片的参数(inSampleSize)、各种transform变换

  • 读取:当内存缓存未命中且要检查磁盘缓存时读取,如果命中就直接将数据解码并返回。

  • 写入:原图资源解码后,调用DecodeJob.notifyEncodeAndRelease(), 注意缓存key(ResourceCacheKey)

  • 剔除:LRU算法规则

DataCache

  • 图片原始数据在磁盘中的缓存(从网络、文件中直接获得的原始数据)

  • 读取:当以上缓存均未命中时读取,如果命中先将数据转换一下再解码并返回。

  • 写入:图片原始资源加载完成后,将其写入磁盘缓存(默认写入可配置),注意缓存key (DataCacheKey)

  • 剔除:LRU算法规则。

为什么要设计活动资源(ActiveResources)缓存?

activeResources就是一个弱引用的HashMap,用来缓存正在使用中的图片。这样可以保护这些正在使用的图片不会被LruCache算法回收掉。

缓存算法如何实现的?

内存:LRUCache 、 LinkedHashMap
磁盘:基于LinkedHashMap自己实现的DiskLruCache;两层磁盘缓存使用了不同的key而已。

BitmapPool又是何用?

复用创建过的Bitmap对象。

  • 写入:内存缓存溢出时、EngineResource.release()至引用数为0和ActiveResources被GC回收后如果不使用内存缓存,会直接将其放入bitmapPool等待复用。

  • 读取:需要创建Bitmap的地方,如果复用池已存在可用的bitmap则直接返回,没有则创建新的bitmap返回。

  • 剔除:超过size后溢出、不支持复用直接剔除。

当一个Bitmap从内存缓存 被动 的被移除(内存紧张、达到maxSize)的时候并不会被recycle。而是加入这个BitmapPool,只有从这个BitmapPool 被动被移除的时候,Bitmap的内存才会真正被recycle释放。

使用条件: 参考文档

  • Bitmap的inMutable需要为true。

  • Android 4.4及以上只需要被复用的Bitmap的内存必须大于等于需要新获得Bitmap的内存,则允许复用此Bitmap。

  • 4.4以下(3.0以上)则被复用的Bitmap与使用复用的Bitmap必须宽、高和Config相等,才允许复用。

  • 使用HardwareBitmap时不可复用。

Bitmap在什么情况下才被recycle释放内存?

  1. 如果bitmap对象无法复用,在内存缓存中被算法剔除后就会调用recycle释放内存。
  2. 当一个bitmap对象在bitmapPool中被算法移除时。

App内存吃紧时如何避免OOM?

监听onLowMemory、onTrimMemory回调,及时释放memoryCache、bitmapPool、arrayPool

参考

  • Glide on GitHub
  • 深入理解Glide

能力有限,错误难免,如您发现,还望赐教,评论交流,私信讨论。

你可能感兴趣的:(提问Glide - 缓存篇)