Glide 作为一个强大的图片加载框架, 已经被 Android 官方使用, 所以, 明白 Glide 的加载流程以及原理对加深我们对 glide 的理解是很重要的.
本文基于 glide 4.11
Glide.with(this).load("").into(new ImageView(this));
我们从这一句入手, 先看看 Glide 的初始化过程, 也就是 Glide.with(this) 这个方法.
一, 单例实例化
可以看到里面有多个重载方法, 最常用的是这个, 这些方法最终返回的是 RequestManager .
都一致调用了 getRetriever(...).get(view).
我们看一下 getRetriever(...) 里面做了什么.
getRequestManagerRetriever() 返回的是一个 RequestManagerRetriever, 我们主要看的是 Glide.get(context)
可以看到 Glide.get(context) 里面进行了初始化的操作, 它是我们熟悉的单例模式. 最终会调用
二, GlideModule 配置加载
上面的 get 方法中, 我们需要注意这一句:
- GeneratedAppGlideModule annotationGeneratedModule =
- getAnnotationGeneratedGlideModules(context.getApplicationContext());
点进去可以看到关键部分的代码为
Glide 提供给我们自定义加载组件的方式, 在 Glide 3x 中, 我们首先会定义一个继承于 GlideModule 的类, 然后在项目的 AndroidMenifest.xml 中进行指定:
- <meta-data Android:name="com.test.GlideConfiguration"
- Android:value="GlideModule"/>
而在 Glide4 中, 提供另外一个配置的模式, 那就是注解, 并且不再继承 GlideModule, 而是继承 AppGlideModule 和 LibraryGlideModule, 分别对应 Application 和 Library, 使用 @GlideModule 注解进行标记. 而 Glide3.x 中的配置方式已经建议放弃使用.
getAnnotationGeneratedGlideModules(context.getApplicationContext()); 便是获取 Glide 注解自动生产的一个 Glide 的 Module 配置器, 叫做:
GeneratedAppGlideModuleImpl
然后将其作为参数最终传递到 initializeGlide 方法.
initializeGlide 方法:
上面这一段的意思就是: 从 manifest 中解析到我们自定义的 GlideModule 类, 如果判断与注解生成的类重复, 那么就可以去掉.
annotationGeneratedModule.isManifestParsingEnabled()
判断是否还支持 Glide 3x 的在 AndroidMenifest.xml 中进行指定的方式, 默认是返回 true, 说明现在还是支持的.
接着以上代码, Glide 将逐个调用剩下的 GlideModule, 并回调 applyOptions 和 registerComponents 接口, 这时, 用户配置的 GlideModule 就会被调用, 同时用户设置的参数也就被配置到 Glide 中.
源码中获取的通过注解生成的 GlideModule 只有一个, 这也说明了我们只能通过注解配置一次.
三, 构建 Glide
Glide glide = builder.build(applicationContext);
build 方法里面是对 glide 的各种配置, 比如上面的:
1, 加载源数据的线程池
2, 加载磁盘缓存中数据的线程池 (不能用来加载 url 网络数据)
3, 动画加载请求器
4, 内存计算器
5, 网络状态检测器
6,bitmap 缓存池 (避免不断不断创建与回收 bitmap 导致内存抖动)
7, 数组资源缓存池
8, 内存缓存, 缓存完成加载和显示的图片数据资源
9, 本地磁盘缓存, 默认存储在 App 内部私密目录
然后创建图片加载引擎.
最后再将上面的缓存池, 引擎等作为参数, 构建一个 Glide
这个构造函数非常长, 我们只挑一些重点的来讲, 其它的可以类推:
1, 创建各种 decoder, 也就是解码器, 比如:
- ByteBufferGifDecoder byteBufferGifDecoder =
- new ByteBufferGifDecoder(context, imageHeaderParsers, bitmapPool, arrayPool);
将 ByteBuffer 解码为 GifDrawable.
ResourceDrawableDecoder resourceDrawableDecoder = new ResourceDrawableDecoder(context);
将资源 uri 解码为 Drawable
2, 创建各种 factory, 即模型装换器, 比如:
- ResourceLoader.StreamFactory resourceLoaderStreamFactory =
- new ResourceLoader.StreamFactory(resources);
将 Android 资源 ID 转换为 Uri, 在加载成为 InputStream
ResourceLoader.UriFactory resourceLoaderUriFactory = new ResourceLoader.UriFactory(resources);
将资源 ID 转换为 Uri
3, 创建各种 Transcoder, 即转码器, 比如
BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
将 Bitmap 转码为 Byte arrays
GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();
将将 GifDrawable 转码为 Byte arrays
4, 创建各种 encoder, 即编码器, 比如:
BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);
将 Bitmap 数据缓存为 File
5, 注册:
如上面, 注册将 Byte 数据缓存为 File 的编码器, 注册将 InputStream 缓存为 File 的编码器. 将 ByteBuffer 解码为 Bitmap 的解码器, 将 inputStreams 解码为 Bitmap 的编码器.
四, 生命周期管理.
getRetriever(activity).get(activity); 中的 getRetriever(activity) 方法讲解完了, 接下来讲 get 方法, 大家就能知道 glide 是怎么监听图片的生命周期的.
同样的, get 方法也有多个重载方法, 方法里面检测, 如果是运行在后台线程, 那都会调用下面这个方法:
因为不是运行在主线程, 所以最终也都会调用:
getApplicationManager(context), 创建一个 RequestManager, 生命周期与 application 的一样.
而如果不是运行在后台线程的话, 那么重载方法里面的参数不同, 执行的方法也就不同, 我且看这一个:
public RequestManager get(@NonNull Activity activity)
传递的参数是 activity, 那么生命周期应该与 Activity 一样.
我们点进去 fragmentGet 方法:
可以看到它首先获取 RequestManagerFragment, 这其实就是一个 fragment, 然后获取与之绑定的 RequestManager, 如果获取不到就说明还没绑定, 那么就去构建一个 RequestManager, 然后与 RequestManagerFragment 进行绑定. 而在构建 RequestManager 的时候, 传进去了一个 current.getGlideLifecycle(), 这个是 Glide 的生命周期, 可以看出生命周期的管理是在 RequestManager 中的. 那怎么实现与 activity 的生命周期同步呢?
接下来就要看看 getRequestManagerFragment(fm, parentHint, isParentVisible); 这个方法做了什么.
首先通过 tag 去找 activity 中有没有存在对应的 fragment, 找不到的话就去 pendingRequestManagerFragments 这个 map 中看有没有, 还没有的话就去初始化一个 RequestManagerFragment.
再将 fragment 添加到 activity 中.
pendingRequestManagerFragments 的作用:
pendingRequestManagerFragments 是为了防止重复添加 fragment. 因为 add 方法来添加 fragment 并不会立即执行, 而是被加入任务队列中. 它有相关的生命周期是异步进行的, 所以如果 add 之后立马又在相同 fragment 或者 activity 环境中调用 get 方法, 那么就很有可能又创建一个新的 RequestManagerFragment, 所以用 pendingRequestManagerFragments 在 add 任务完成前拦截其他的添加操作, 在完成后发送消息移除.
- if (isParentVisible) {
- current.getGlideLifecycle().onStart();
- }
如果父布局可见, 也就是 activity 可见, 那么开始生命周期的 start 回调.
在 RequestManagerFragment 里面可以看到, fragment 的生命周期进行回调的时候就会调用 glide 自定义的生命周期 lifecycle 的相应方法.
也就是说 glide 是通过往 activity 中添加 fragment, 然后监听 fragment 的生命周期来控制 glide 的生命周期进行同步
其它的重载方法类推.
来源: https://www.cnblogs.com/tangZH/p/12409849.html