Glide4.10 加载网络图片的基本流程
Glide.with(context).load(url).into(imageView);
加载一张图片,主要经过上面三个步骤; 下面会逐个分析三个步骤;
本文针对的Glide 4.10版本;
第1步:with(context)
生成RequestManager对象
- 根据context是否是Application,Glide决定是否需要关注页面的生命周期;
- Glide通过添加一个空Fragment的方式感知生命周期变化;
第2步:load(url)
生成RequestManager对象
- 大部分api在这个阶段添加到RequestManager, 比如
listener()
; - 该阶段指定了model类型,本例中model是String类型的url;
第3步:into(imageView)
- 首先,使用imageView构造Target,
into()
主要任务:创建并且执行 Request:requestManager.track(target, request);
- 随后,执行Request的
begin()
方法, 本例为SingleRequest对象的begin()
; - 执行Target的
getSize()
指定所需宽高;此时自定义Target可以设置想要的宽高; - 最后,执行SingleRequest的
onSizeReady()
, 调用Engine对象的load()
方法开始加载;
第3.1步骤: Engine.load()
加载图片
- 首先试图从内存缓存(内存缓存分两级)中取,
loadFromMemory()
步骤:loadFromActiveResources()
:根据Key从ActivieResources集合获取;- ActivieResources为1级内存缓存,存储当前Activity正在使用的资源;
loadFromCache()
:再从MemoryCache中获取;- MemoryCache为2级内存缓存,该接口的实现类为LruResourceCache;
- 如果
loadFromMemory()
没获取到缓存Resource,则从文件缓存或者数据源获取; - Engine对象
waitForExistingOrStartNewJob()
创建EngineJob和DecodeJob;- EngineJob是从
Pools.Pool<EngineJob<?>> pool
对象池获取;DecodeJob类似; - DecodeJob继承自Runnable;EngineJob会启动DecodeJob;
- EngineJob是从
- DecodeJob的
run()
方法,核心逻辑在DecodeJob的runWrapped()
方法; runWrapped()
方法,主要通过状态机runReason控制;- 首先将状态机runReason初始为
RunReason.INITIALIZE
; - 执行
getNextGenerator()
获取DataFetcherGenerator;- DataFetcherGenerator接口用来获取数据,它有三个具体实现类:
- ResourceCacheGenerator:获取downsampled/transformed的资源数据;
- DataCacheGenerator:获取原始未修改过的资源数据;
- SourceGenerator:意味着从原始数据源获取数据;
- 依次查询上面3个实现类;本例为第一次获取图片情形,currentGenerator最终为SourceGenerator,即需要从Source中取数据;
- DataFetcherGenerator接口用来获取数据,它有三个具体实现类:
- 执行currentGenerator的
startNext()
,核心逻辑:寻找合适的LoadData,进而生成Fetcher,执行Fetcher的loadData()
方法获取InputStream;- 从ModelLoader集合中寻找合适的ModelLoader,依据是
boolean handles(Model)
, 该方法返回true表示可以处理该Model;- Glide对象初始化时注册所有ModelLoader,将其存储在Registry对象中;
- ModelLoader列表可以通过GlideContext获取;
- 本例为加载网络图片,Loader为HttpUriLoader,因为它的
handles()
方法是判断scheme是否为http或https;
- Glide对象初始化时注册所有ModelLoader,将其存储在Registry对象中;
- HttpUriLoader的model是Uri类型,它将model包装为GlideUrl类型,将load工作交给HttpGlideUrlLoader的
buildLoadData()
; - HttpGlideUrlLoader的
buildLoadData()
创建用于网络通信的HttpUrlFetcher对象;网络通信的结果是InputStream, 随后需要将其decode为Resource; - fetcher拿到IS后,回调DecodeJob的
onDataFetcherReady(Key, Resource ...)
;
- 从ModelLoader集合中寻找合适的ModelLoader,依据是
- DecodeJob通过回调拿到fetcher,执行
decodeFromRetrievedData()
解码,拿到Resource对象;- 执行
decodeFromData()
获取Resource, 具体逻辑在decodeFromFetcher()
:decodeHelper.getLoadPath()
获取LoadPath;- 首先通过
getDecodePaths()
获取DecodePath列表;- DecodePath和ModelLoader类似,都是注册在Registry,也是通过
handles()
方法判断;
- DecodePath和ModelLoader类似,都是注册在Registry,也是通过
- 本例的DecodePath列表中只包含ByteBufferBitmapDecoder;
- 使用DecodePath列表创建并返回一个LoadPath:
- 首先通过
- 执行LoadPath的
runLoadPath()
方法:返回Resource;- 遍历DecodePath列表,调用
DecodePath.decodeResource()
进行解码; - 解码完成后,回调DecodeJob的
onResourceDecoded()
, 执行Transform、缓存等操作; - 本例Resource为Bitmap, 实际上Bitmap/Drawable/Gif等都实现Resource接口;
- 遍历DecodePath列表,调用
- 拿到Resource后,调用DecodeJob的
notifyEncodeAndRelease()
; - 回调EngineJob的
onResourceReady(Resource)
,进一步执行notifyCallbacksOfResult()
:- 回调Engine的
onEngineJobComplete()
,将Resource保存到内存缓存中; - 回调SingleRequest的
onResourceReady()
: 回调listener(new RequestListener)
中逻辑;
- 回调Engine的
- 执行
- SingleRequest回调Target的同名方法
onResourceReady()
,完成最终的显示;- 本例执行
into(ImageView)
,则会执行ImageViewTarget的onResourceReady()
; - ImageViewTarget的
onResourceReady()
调用抽象方法setResource(Resource)
,如果执行过asBitmap()
, 便执行BitmapImageViewTarget的setResource()
,具体为view.setImageBitmap(resource)
;
- 本例执行
- 此时图片便加载出来了;