前言
近期研究了一下Glide的图片加载框架,在这里和大家分享一下。由于代码研读有限,难免有错误的地方,了解的童鞋还望指正。学习小组QQ群: 193765960。
本篇是Glide框架及源码解析的第三篇,更多文章敬请关注后续文章。如果这篇文章对大家学习Glide有帮助,还望大家多多转载。
版权归作者所有,如有转发,请注明文章出处:https://xiaodanchen.github.io/archives/
相关文章:
跟着源码学设计:Glide框架及源码解析(一)
跟着源码学设计:Glide框架及源码解析(二)
跟着源码学设计:Glide框架及源码解析(三)
跟着源码学设计:Glide框架及源码解析(四)
跟着源码学设计:Glide框架及源码解析(五)
Glide内存缓存机制
在之前的两篇中我们剖析了Glide的生命周期绑定机制和Glide的请求管理机制。接下来按说应该讲到request实际请求资源并回调刷新界面这一块了,但是为了更好的理解Glide在这一块的设计,我先大致的讲一讲Glide的内存缓存和管理机制。
不同于其他常见网络加载框架只有LruCatch一种缓存机制,Glide内存为三块(非常牛逼巧妙的设计):
- ActiveResourceCache:缓存当前正在使用的资源(注意是弱引用)
- LruResourceCache: 缓存最近使用过但是当前未使用的资源,LRU算法
- BitmapPool:缓存所有被释放的图片,内存复用,LRU算法
注意:
- LruResourceCache和ActiveResourceCache设计是为了尽可能的资源复用
- BitmapPool的设计目的是为了尽可能的内存复用
说的比较抽象,是不是懵逼了?别急,上图:
- 当我们需要显示某个资源时,Glide会先去查找LruResourceCache,找到了则将资源从LruResourceCache移除加入到ActiveResourceCache;
- LruResourceCache找不到资源则查找ActiveResourceCache。
- 如果在ActiveResourceCache也找不到合适的资源,则会根据加载策略从硬盘或者网络加载资源。
- 获取数据后Glide会从BitmapPool中找寻合适的可供内存复用的废弃recycled bitmap(找不到则会重新创建bitmap对象),然后刷新bitmap的数据。
- bitmap被转换封装为Resource缓存入ActiveResourceCache和Request对象中。
Request的target会获取resource中引用的bitmap并展示。
当target的资源需要release时,resource会根据缓存策略被缓存到LruResourceCache,同时ActiveResourceCache中的弱引用会被删除。如果,该资源不能缓存到LruResourceCache,则资源将被recycle到BitmapPool。
当需要回收内存时(比如系统内存不足或者生命周期结束),LruResourceCache将根据LRU算法recycle一些resource到BitmapPool。
- BitmapPool会根据缓存池的尺寸和recycled resource的缓存策略来缓存resource的bitmap。
- BitmapPool会根据LRU算法和缓存池的尺寸来释放一些老旧资源。
- 当系统GC时,则会回收可回收的资源释放内存
这样就完成了一个资源的完整的循环。
BitmapPool的内存复用机制
知识储备:
- BitmapFactory.Options.inBitmap是AndroiD3.0新增的一个属性,如果设置了这个属性则会重用这个Bitmap的内存从而提升性能。
- 在SDK 11 -> 18之间,重用的bitmap大小必须是一致的,例如给inBitmap赋值的图片大小为100-100,那么新申请的bitmap必须也为100-100才能够被重用。从SDK 19开始,新申请的bitmap大小必须小于或者等于已经赋值过的bitmap大小。
- 新申请的bitmap与旧的bitmap必须有相同的解码格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444与565格式的bitmap了
使用inbitmap前,内存占用情况
使用inbitmap后,内存占用情况
下面看一下核心代码:Downsampler的downsampleWithSize()方法
|
|
让我们先看一下我们最常见到的LruMemoryCache机制
- 如图,当系统内存不足时,LruMemoryCache会根据LRU算法移除一些资源(bitmap)
- 针对移除的资源,系统在GC时会回收资源(bitmap)以释放内存
- 当应用再次需要次资源时,需要重新分配内存,重新对资源文件进行解析生成bitmap
1)这样会造成内存抖动;
2)比较耗费时间,影响流畅度(GC也比较频繁)
让我们再来看一下Glide的机制
- 如图,当系统内存不足时,LruResourceCache会根据LRU算法移除一些资源(resource)到BitmapPool
- 到BitmapPool会根据LRU算法移除一些资源(bitmap)
- 当应用再次需要资源时,会优先复用到BitmapPool中的bitmap对象(复用其内存),只需刷新bitmap的像素数据
1)这样能有效地降低内存抖动;
2)由于很多情况下可以复用废弃bitmap的内存,因此避免了内存分配等造成的性能损耗,系统比较流畅
3)降低了系统GC的频率
4)LruResourceCache和BitmapPool中都是当前不在使用的资源,做整体的资源回收那叫一个酸爽。
(本篇是Glide框架及源码解析的第三篇,更多文章敬请关注后续文章。版权归作者所有,如有转发,请注明文章出处:原文链接)