前言
Glide
可以说是最常用的图片加载框架了,Glide
链式调用使用方便,性能上也可以满足大多数场景的使用,Glide
源码与原理也是面试中的常客。
但是Glide
的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点.
本文以Glide
做了哪些优化为切入点,介绍与学习Glide
的源码与原理,如果对您有所帮助,欢迎点赞.
Glide
做了哪些优化?
要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题?
1.图片下载是个耗时过程,我们首先需要考虑的就是图片缓存的问题
2.图片加载也是个耗内存的操作,很多OOM
都是图片加载导致的,所以我们也要考虑内存优化问题
3.图片加载到一半,页面关闭了,图片加载也应该中止,这又牵扯到了生命周期管理的问题
4.还有就是图片加载框架是否支持大图加载?大图情况下会有什么问题?
以上就是我们提出的有关于Glide
的几个问题了,这样我们可以轻松得出本文主要包括的内容
1.Glide
图片加载的总体流程介绍
2.Glide
缓存机制做了哪些优化?
3.Glide
做了哪些内存优化?
4.Glide
如何管理生命周期?
5.Glide
怎么做大图加载?
下面就带着问题进入正文~
1.Glide
图片加载总体流程介绍
在开始了解Glide
具体做了哪些优化之前,我们先对Glide
图片加载的总体流程做一个简单的介绍,让大家首先有个整体概念。
同时在后面对Glide
做的优化具体发生在哪一步也可以方便的知道.
概括来说,图片加载包含封装,解析,下载,解码,变换,缓存,显示等操作,如下图所示:
- 1.封装参数:从指定来源,到输出结果,中间可能经历很多流程,所以第一件事就是封装参数,这些参数会贯穿整个过程;
- 2.解析路径:图片的来源有多种,格式也不尽相同,需要规范化;
- 3.读取缓存:为了减少计算,通常都会做缓存;同样的请求,从缓存中取图片(
Bitmap
)即可; - 4.查找文件/下载文件:如果是本地的文件,直接解码即可;如果是网络图片,需要先下载;
- 5.解码:这一步是整个过程中最复杂的步骤之一,有不少细节;
- 6.变换:解码出
Bitmap
之后,可能还需要做一些变换处理(圆角,滤镜等); - 7.缓存:得到最终bitmap之后,可以缓存起来,以便下次请求时直接取结果;
- 8.显示:显示结果,可能需要做些动画(淡入动画,crossFade等)。
以上就是Glide
图片加载的总体流程,这里只做了简单的介绍,详情可见:聊一聊关于Glide在面试中的那些事
2.Glide
缓存机制做了哪些优化?
我们知道,下载图片是非常耗费资源的,所以图片缓存机制是图片加载框架很重要的一部分,下面就以一张表格来说明下 Glide 缓存。
缓存类型 | 缓存代表 | 说明 |
---|---|---|
活动缓存 | ActiveResources | 如果当前对应的图片资源是从内存缓存中获取的,那么会将这个图片存储到活动资源中。 |
内存缓存 | LruResourceCache | 图片解析完成并最近被加载过,则放入内存中 |
磁盘缓存-资源类型 | DiskLruCacheWrapper | 被解码后的图片写入磁盘文件中 |
磁盘缓存-原始数据 | DiskLruCacheWrapper | 网络请求成功后将原始数据在磁盘中缓存 |
在介绍具体缓存前,先来看一张加载缓存执行顺序,有个大概的印象
Glide
的缓存机制,主要分为2种缓存,一种是内存缓存,一种是磁盘缓存。
之所以使用内存缓存的原因是:防止应用重复将图片读入到内存,造成内存资源浪费。
之所以使用磁盘缓存的原因是:防止应用重复的从网络或者其他地方下载和读取数据。
正式因为有着这两种缓存的结合,才构成了Glide
极佳的缓存效果。
2.1 内存缓存
Glide
默认开启内存缓存,我们也可以通过skipMemoryCache
关闭
上面我们可以看到内存缓存其实分两个部分,ActiveResource
缓存与LRU
缓存
ActiveResources
就是一个弱引用的 HashMap
,用来缓存正在使用中的图片,使用 ActiveResources
来缓存正在使用中的图片,可以保护这些图片不会被 LruCache
算法回收掉
内存缓存加载顺序如下:
1.根据图片地址,宽高,变换,签名等生成key
2.第一次加载没有获取到活动缓存。
3.接着加载内存资源缓存,先清理掉内存缓存,在添加进行活动缓存。
4.第二次加载活动缓存已经存在。
5.当前图片引用为 0 的时候,清理活动资源,并且添加进内存资源。
6.又回到了第一步,然后就这样环环相扣。
总结为流程图如下:
这里没有贴出源码,如果想要看源码的同学可参考:从源码的角度分析 Glide 缓存策略
我们上面总结了Glide
内存缓存加载的流程,看到这里我们很容易有个疑问,为什么Glide
要设计两种内存缓存?