写在文章之前,先分享一篇动脑学院的Glide缓存文章:
https://www.jianshu.com/p/97fd67720b34
Glide在开始一个新的图片请求之前会检查以下多级缓存:
1.活动资源(Activity Resource);
2.内存缓存(Memory Cache);
3.磁盘缓存(又分为Resource DiskCache和 DataDisCache);
第一层 活动资源
当需要加载某张图片能够出内存缓存中获得的时候,在图片加载时主动将对应图片从内存缓存中移除,加入到活动资源中。
这样也可以避免因为达到内存缓存最大值或者系统内存压力导致的内存缓存清理,从而释放掉活动缓存中的图片(recycler)。
活动资源中是一个”引用计数“的图片资源的弱引用集合。
因为同一张图片可能在多个地方被同时使用,每一次使用都会讲计数+1,而当引用计数为0时,则表示这个图片没有被使用也就是没有强引用了,这样则会讲图片从活动资源中移除,并加入内存缓存。
加入内存缓存
第二层 内存缓存
内存缓存默认使用LRU(缓存淘汰算法/最近最少使用算法),当Bitmap从活动资源移除的时候,会加入内存缓存。使用图片的时候会主动从此缓存移除,加入活动资源缓存。
LRU在Android support-v4中提供了LruCache工具类。
LruCache
构造LinkedHashMap的accessOrder设置为true,在使用此map时候,自动进程排序(每次get/put会将使用的value放入链表header头部)。LruCache会在每次get/put的时候判断数据如果达到了maxSize,则会优先删除tail尾端的数据。
磁盘缓存同样使用LRU算法。
第三、四层 磁盘缓存
Resource缓存的是经过解码后的图片,如果再使用就不需要再去进行解码配置(BitmapFactory.Options),加快获得图片速度。比如原图是一个100100的ARGB_8888图片,在首次使用的时候需要的是5050的RGB_565图片,那么Resource将50*50 RGB_565缓存下来,再次使用此图片的时候就可以从Resource获得。不需要去计算inSampleSize(缩放因子)。
Data缓存的则是图像的原始数据。
Bitmap复用
如果缓存都不存在,那么会从源地址获得图片(网络或是文件)。而在解析图片的时候会需要BitmapPool(复用池),达到复用的效果。
复用并不能减少程序正在使用的内存大小,Bitmap复用,解决的是减少频繁申请内存带来的性能(抖动、碎片)问题。
根据Google给出的案例,使用方式为在解析的时候设置Options的inBitmap属性。
- Bitmap的inMutable(异变)需要为true;
- Android4.4以上只需要被复用的Bitmap内存必须大于等于需要新获得Bitmap的内存,则允许复用此Bitmap内存;
- 4.4以下(3.0以上)则被复用的Bitmap与使用复用的Bitmap必须宽、高相等并且使用复用的Bitmap解码时设置的inSampleSize为1,才允许复用;
因此Glide中,在每次解析一张图片为Bitmap的时候,会从BitmapPool中查找一个可被复用的Bitmap。
BitmapPool是Glide中的Bitmap复用池,同样适用于LRU来管理。
当一个Bitmap从内存缓存被动的移除时候,并不会被recycler。而是加入这个BitmapPool,只有从这个BitmapPool被动移除的时候,Bitmap内存才会真正的被recycler释放。
网友评论