文章目录
前言
Glide是一款非常好用的图片加载框架那么它具体好用在哪里呢?
总所周知,在android开发中有几大令人头疼的问题,比如内存泄漏,线程问题,生命周期,这些问题在Glide的身上都不需要关心,下面就具体来介绍一下Glide的使用及原理吧。
一、Glide的基本使用
Glide.with(MainActivity.this)
.load(url)
.asGif() // 加载gif图片
.placeholder(res) // 加载成功前显示图片
.diskCacheStrategy(DiskCacheStrategy.NONE) // 不使用Glide缓存
.error(res2) // 加载图片失败显示的图片
.into(imageView); // 显示图片
二、Glide的网络请求
1.HttpURLConnection实现一个原生图片加载框架
- 子线程请求网络
- 渲染UI
- 切换到主线程
- 将流转成Bitmap
- Bitmap设置到imageView
Glide的网络请求也是HttpURLConnection
2.Glide为什么能监听网络变化
监听网络变化,重新进行一次网络请求restartRequests(),其中request.begin()
LRU算法:LinkedHashMap,双向链表,查询快,最近访问的元素在栈顶
切换线程Handler:EngineRunnable中切岛子线程,走三级缓存,若没有走网络请求,into之前切回主线程
三、Glide的生命周期
1.Fragment的生命周期,动态加载Fragment
-
onAttach():关联之后调用
-
onCreate():Fragment初次创建时调用(不能去拿activity的UI控件)
-
onCreateView():设置fragment的view
-
onActivityCreated(): 可以拿activity的UI控件
activity先onCreate(),后onDestroy()
无UI的Fragment,没有视图,只是进行声明周期的监听
into时会判断是否为主线程
onDestroy()会清除内存,硬盘文件没有被清除
2.Glide如何管理管理生命周期
RequestManagerRetriever创建一个无UI的Fragment,传到Activity上,并将这个Fragment的生命周期绑定到RequestManager上
-
如果当前页面停止,onStop()方法被调用,所有运行中的请求都会停止,加入到等待队列中,开始运行后,放回运行队列中
-
当Activity调用onStop()时,隐式调用Fragment的onStop()方法,通过调用RequestManager,来管理两个队列的请求
3.Glide为什么要缓存Fragment
SupportRequestManagerFragment中缓存
1、防止每次都创建一个Fragment(复用)
2、当前Fragment放进去会把上一个Fragment移除(不会造成内存泄露)
3、多个activity时,防止多个Fragment导致管理生命周期紊乱,保证只有一个Fragment,保证Glide的生命周期和当前显示的Activity保持一致
四、Glide如何监测内存
Activity和Fragment中都有一个ComponentCallback接口,里面onTrimMemory方法(回调接口)
而Glide在RequestManagerFragment中监听onTrimMemory,onLowMemory中glide.clearMemory(),clearMemory中对内存缓存和BitmapPool进行清除
key不变,value变了,还是请求原来的图片(有缓存)
五、Glide的三大主线
Glide.with(this).load(url).into(iv_image1);
1.Glide的with主线
-
new一个Glide对象:build构建者模式
-
创建了一个空Fragment:绑定生命周期实现了Lifecycle接口
-
把生命周期方法传导出去
2.Glide的load主线
构建RequestBuilder对象,把Url传进去
3.Glide的into主线
-
engine.load中三级缓存(EngineKey)
-
活动缓存(Hashmap)(弱引用缓存)
-
内存缓存(Lru算法)
-
磁盘缓存(Lru算法)
-
-
从主线程切换到子线程去请求网络数据
-
切回主线程
-
主线程渲染数据
-
图片裁剪,自适应
六、Glide三大缓存
通过key值去取,存的时候把key存进去
-
活动缓存:针对当前activity有效,activity被干掉就没了
-
内存缓存:针对当前app有效(Lru,有数量限制)
-
磁盘缓存:app没被卸载就有效
1、手写活动缓存(activityCache):get,set,remove
-
Lru无法识别特殊字符串,通过算法将url转成一个key
-
不能一边遍历,一边删除,数组长度变化,会下标越界
-
删除:通过迭代器去删除
2、手写内存缓存(memoryCache):继承Lruche,设定一个最大值
3、手写磁盘缓存(DiskLruCache):io交互,内存问题,算法
- 单例模式,文件路径,DiskLruCache,get,put
4、Engine引擎:读取缓存,读取逻辑,事件分发给EngineJob
-
从服务器读取图片之后存到磁盘缓存,当前activity可见存到活动缓存(弱引用持有数据,不会造成OOM),不可见存到内存缓存
-
读取逻辑:
-
先找活动缓存,活动缓存中有,存入内存缓存,活动缓存中删除
-
没有,找内存缓存,内存缓存中有,存入活动缓存,内存缓存中删除(相互互补互删)
-
没有,去找磁盘缓存
-
-
EngineJob:继承自Runnable,做网络请求
5、活动缓存和内存缓存区别
-
作用域不同
-
内存缓存有maxSize
6、Glide缓存会缓存两份,不是三份
7、Glide存是若没有设置大小,会存一个和手机分辨率匹配的图片
总结
Glide整体流程: