Glide源码解析一,初始化
转载请标明出处:https:////www.cnblogs.com/tangZH/p/12409849.html
更多精彩文章:http://77blogs.com/?p=269
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的生命周期进行同步
其它的重载方法类推。
Glide源码解析一,初始化的更多相关文章
- SpringMVC源码解析- HandlerAdapter初始化
HandlerAdapter初始化时,主要是进行注解解析器初始化注册;返回值处理类初始化;全局注解@ControllerAdvice内容读取并缓存. 目录: 注解解析器初始化注册:@ModelAttr ...
- mybatis源码解析7---MappedStatement初始化过程
上一篇我们了解到了MappedStatement类就是mapper.xml中的一个sql语句,而Configuration初始化的时候会加载所有的mapper接口类,而本篇再分析下是如何将mapper ...
- Vue.js源码解析-Vue初始化流程
目录 前言 1. 初始化流程概述图.代码流程图 1.1 初始化流程概述 1.2 初始化代码执行流程图 2. 初始化相关代码分析 2.1 initGlobalAPI(Vue) 初始化Vue的全局静态AP ...
- Glide源码解析
基本使用方法: Glide.with(this) .asDrawable() .load("http://i6.topit.me/6/5d/45/1131907198420455d6o.jp ...
- Glide源码解析二---into方法
转载请标明出处,维权必究: https://www.cnblogs.com/tangZH/p/12543154.html Glide作为一个强大的图片加载框架,已经被android官方使用,所以,明白 ...
- Vue.js源码解析-Vue初始化流程之动态创建DOM
目录 前言 一._update 如何判断是初始化还是更新操作? 二.patch 2.1 patch 定义 2.2 初始化的 patch 三.createElm 动态创建DOM 3.1 创建组件节点 3 ...
- Android AsyncTask 源码解析
1. 官方介绍 public abstract class AsyncTask extends Object java.lang.Object ↳ android.os.AsyncTask&l ...
- myBatis源码解析-配置文件解析(6)
前言 本来打算此次写一篇关于SqlSession的解析,但发现SqlSession涉及的知识太多.所以先结合mybatis配置文件(我们项目中常写的如mybatisConfig.xml),来分析下my ...
- 源码解析C#中PriorityQueue(优先级队列)的实现
前言 前段时间看到有大佬对.net 6.0新出的PriorityQueue(优先级队列)数据结构做了解析,但是没有源码分析,所以本着探究源码的心态,看了看并分享出来.它不像普通队列先进先出(FIFO) ...
随机推荐
- django,inspectdb,操作已经存在的表
1.Django附带了一个名为inspectdb程序,它可以通过现有数据库来创建模型,并将相关模型代码另存到指定文件中.在新建的newmodels.py文件中挑选指定表格对应的模型代码,并将其复制到相 ...
- linux通过grep根据关键字查找日志文件上下文
linux通过grep根据关键字查找日志文件上下文 1.在标准unix/linux下的grep命令中,通过以下参数控制上下文的显示: grep -C 10 keyword catalina.out 显 ...
- python-django框架-电商项目-用户模块开发_20191117
实现注册的基本逻辑: 1,注册页面 注意:注册页面需要静态文件的支持,另外注册页面是基础基类的, 1,url,路由系统, 2,views,视图系统,还是使用类视图,里面有很多的函数, 2,views. ...
- HBase单机安装及Phoenix JDBC连接
HBase是建立在Hadoop文件系统之上的分布式面向列的数据库,它是横向扩展的.它利用了Hadoop的文件系统(HDFS)提供的容错能力. HBase提供对数据的随机实时读/写访问,可以直接HBas ...
- ISIS
R1到R6配置ip和环回口 交换机不用配置 R6多加10.0.1.1 10.0.2.1 10.0.3.1 三个环回口 需求: 1.假如你是公司A网络管理员,公司A网络如图所示,现公司A要求如下:() ...
- 网站爬取-案例三:今日头条抓取(ajax抓取JS数据)
今日头条这类的网站制作,从数据形式,CSS样式都是通过数据接口的样式来决定的,所以它的抓取方法和其他网页的抓取方法不太一样,对它的抓取需要抓取后台传来的JSON数据,先来看一下今日头条的源码结构:我们 ...
- php7 安装mongodb扩展
下载 mongodb-1.6.0.tgz wget https://pecl.php.net/get/mongodb-1.6.0.tgz 版本太低的话有些语法不一样,起码1.5以上吧 进入 mo ...
- 实战_3:新建产品配置(product)并导出项目
产品配置Product 产品配置用于定义和管理RCP应用的多个方面特征.并支持将RCP项目导出为部署包(类似eclipse压缩包),可以直接部署到其他环境上使用. 产品配置必须新建一个 扩展名为 .p ...
- Docker部署Python爬虫项目
1) 首先安装docker: # 用 yum 安装并启动 yum install docker -y && systemctl start docker 2) 下载自定义镜像需要用到的 ...
- 学习python-20191108(1)Mysql、Flask
一.使用pymysql模块操作MYSQL 导入pymysql模块: pip install pymysql 1.增删改 import pymysql # 定义数据库连接信息 config = { ...