Glide源码解析一,初始化
转载请标明出处:https:////www.cnblogs.com/tangzh/p/12409849.html
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"/>
getannotationgeneratedglidemodules(context.getapplicationcontext());便是获取glide注解自动生产的一个glide的module配置器,叫做:
generatedappglidemoduleimpl
然后将其作为参数最终传递到initializeglide方法。
initializeglide方法:
上面这一段的意思就是:从manifest中解析到我们自定义的glidemodule类,如果判断与注解生成的类重复,那么就可以去掉。
annotationgeneratedmodule.ismanifestparsingenabled()
判断是否还支持glide 3x的在androidmenifest.xml中进行指定的方式,默认是返回true,说明现在还是支持的。
build方法里面是对glide的各种配置,比如上面的:
1、加载源数据的线程池
2、加载磁盘缓存中数据的线程池(不能用来加载url网络数据)
3、动画加载请求器
4、内存计算器
5、网络状态检测器
6、bitmap缓存池(避免不断不断创建与回收bitmap导致内存抖动)
7、数组资源缓存池
最后再将上面的缓存池,引擎等作为参数,构建一个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的生命周期进行同步
其它的重载方法类推。
上一篇: c#获取客户端IP地址(考虑代理)
推荐阅读
-
netty源码解析(4.0)-28 ByteBuf内存池:PooledByteBufAllocator-把一切组装起来
-
Mybaits 源码解析 (十二)----- Mybatis的事务如何被Spring管理?Mybatis和Spring事务中用的Connection是同一个吗?
-
Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析
-
Spring MVC源码(一) ----- 启动过程与组件初始化
-
Mybaits 源码解析 (十)----- 全网最详细,没有之一:Spring-Mybatis框架使用与源码解析
-
Mybaits 源码解析 (八)----- 全网最详细,没有之一:结果集 ResultSet 自动映射成实体类对象(上篇)
-
Mybaits 源码解析 (九)----- 全网最详细,没有之一:一级缓存和二级缓存源码分析
-
JDK8源码解析 -- HashMap(一)
-
yocto-sumo源码解析(一): oe-init-build-env
-
SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据