Glide总结
2021-01-04 本文已影响0人
陈萍儿Candy
Glide中实现了ComponentCallbacks2,并注册,所以glide可以在系统内存紧张时,回调application的onLowMemory,onTrimMemory等方法时,会回调注册的所有的
ComponentCallbacks2的onLowMemory,onTrimMemory等方法,
glide中onLowMemory方法处理如下
@Override
public void onLowMemory() {
clearMemory();
}
/**
* Clears as much memory as possible.
*
* @see android.content.ComponentCallbacks#onLowMemory()
* @see android.content.ComponentCallbacks2#onLowMemory()
*/
public void clearMemory() {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// memory cache needs to be cleared before bitmap pool to clear re-pooled Bitmaps too. See #687.
memoryCache.clearMemory();
bitmapPool.clearMemory();
arrayPool.clearMemory();
}
onTrimMemory方法根据level去清理对应大小的内存;更合理
/**
* Clears some memory with the exact amount depending on the given level.
*
* @see android.content.ComponentCallbacks2#onTrimMemory(int)
*/
public void trimMemory(int level) {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// Request managers need to be trimmed before the caches and pools, in order for the latter to
// have the most benefit.
for (RequestManager manager : managers) {
manager.onTrimMemory(level);
}
// memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
memoryCache.trimMemory(level);
bitmapPool.trimMemory(level);
arrayPool.trimMemory(level);
}
合理的清理缓存,减少因oom导致crash;
- 看过Glide源码吗,你印象最深的是什么?
Glide的缓存设计可以说是非常先进的,考虑的场景也很周全。在缓存这一功能上,Glide又将它分成了两个模块,
一个是内存缓存,一个是硬盘缓存。这两个缓存模块的作用各不相同,内存缓存的主要作用是防止应用重复将图片数据读取到内存当中,
而硬盘缓存的主要作用是防止应用重复从网络或其他地方重复下载和读取数据。内存缓存和硬盘缓存的相互结合才构成了Glide极佳的图片缓存效果
- 简单说一下Glide的三级缓存?
当我们的APP中想要加载某张图片时,先去activeResources(WeakReference)中寻找,
如果activeResources(WeakReference)中有,则从activeResources(WeakReference)中取出图片使用,
如果activeResources(WeakReference)中也没有图片,则去LruCache(实际上是LruResourceCache,而其继承自LruCache)中寻找图片,
如果LruCache中有,则先保存到activeResources(WeakReference)中再取出来使用,如果LruCache中没有,
则去文件系统中寻找,如果有则取出来使用,同时将图片添加到LruCache中,如果没有,则连接网络从网上下载图片。
图片下载完成后,将图片保存到文件系统中,然后放到LruCache中。严格来讲,并没有什么Glide的三级缓存,因为Glide的缓存只有两个模块,一个是内存缓存,一个是磁盘缓存。其中内存缓存又分为Lru算法的缓存和弱引用缓存。
Glide4.0的缓存机制概况来说就是,先从弱引用缓存中获取数据,假如获取不到,就再尝试从LruCache中获取数据,假如从LruCache中获取到数据的话,就会将其从LruCache中转移到弱引用缓存中,这么做的优点是,下次再来拿数据的时候,就可以直接从弱引用中获取。
资源对象用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1,然后一旦acquired减为0(没有地方引用该资源),就会将其从弱引用中移除,添加到LruCache中。
使用中的资源会用弱引用来缓存,不在使用的资源会添加到LruCache中来缓存。
在二者都获取不到的情况下会根据硬盘缓存策略通过DiskLruCache去硬盘中获取数据,正是这样优秀的缓存机制,让我们在没有网络的情况下也能有很好的体验。
LruCache算法,Least Recently Used,又称为近期最少使用算法。主要算法原理就是把最近所使用的对象的强引用存储在LinkedHashMap上,并且,把最近最少使用的对象在缓存池达到预设值之前从内存中移除。
- Glide如何防止OOM
1.弱引用,activeReFerence
2.onLowMemory,onTrimMemory方法,清理lruchache
- Glide加载一个一兆的图片(100100),是否会压缩后再加载,放到一个200200的view上会怎样,1000*1000呢,图片会很模糊,怎么处理?
使用Glide,我们就完全不用担心图片内存浪费,甚至是内存溢出的问题。因为Glide从来都不会直接将图片的完整尺寸全部加载到内存中,
而是用多少加载多少。Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。
ImageView默认的scaleType是FIT_CENTER,FitCenter的效果:会将图片按照原始的长宽比充满全屏
Glide采样压缩的实现:https://blog.csdn.net/weixin_34416649/article/details/91372458
Downsampler.decode 解析数据流获取Bitmap对象一共有如下几个步骤:
1. 通过数据流解析出图形的原始宽高
2. 获取图形的旋转角度等信息
3. 获取这次图片请求的目标宽高
4. 获取图像的封装格式
JPEG, PNG, WEBP, GIF...
5. 计算 Bitmap 缩放方式
6. 计算 Bitmap 颜色通道
7. 根据采样率计算期望的尺寸
8. 根据期望的宽高从 BitmapPool 中取可以复用的对象, 存入 Options.inBitmap 中, 减少内存消耗
9. 根据配置好的 options 解析数据流
10. 与获取图像原始宽高的操作一致
11. 对图像进行角度矫正
前8步,已经在解析 Bitmap 的时候, 通过给 Options 中的 inBitmap 赋值, 让新解析的 Bitmap 复用这个对象以此来减少内存的消耗
在默认情况下Picasso和Glide的外部缓存机制是非常不一样的,通过实验可以发现(1920x1080 像素的图片被加载到768x432像素的imageview中),Glide缓存的是768x432像素的图片,而Picasso缓存的是整张图片(1920x1080像素)。
当我们调整imageview的大小时,Picasso会不管imageview大小是什么,总是直接缓存整张图片,而Glide就不一样了,它会为每个不同尺寸的Imageview缓存一张图片,也就是说不管你的这张图片有没有加载过,只要imageview的尺寸不一样,那么Glide就会重新加载一次,这时候,它会在加载的imageview之前从网络上重新下载,然后再缓存。
即:如果一个页面的imageview是200*200像素,而另一个页面中的imageview是100*100像素,这时候想要让两个imageview像是同一张图片,那么Glide需要下载两次图片,并且缓存两张图片。