都知道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释放内存?
- 如果bitmap对象无法复用,在内存缓存中被算法剔除后就会调用recycle释放内存。
- 当一个bitmap对象在bitmapPool中被算法移除时。
App内存吃紧时如何避免OOM?
监听onLowMemory、onTrimMemory回调,及时释放memoryCache、bitmapPool、arrayPool
参考
能力有限,错误难免,如您发现,还望赐教,评论交流,私信讨论。