Glide 简单流程分析

简介: 转载请标明地址 QuincySx: http://www.jianshu.com/p/cf8f8f90f621这篇文章是这个系列的第一篇文章,我第一次写这样连续系列的文章,我先一层一层的剥开 Glide ,如果谁有更好的想法欢迎提出。

转载请标明地址 QuincySx: http://www.jianshu.com/p/cf8f8f90f621


这篇文章是这个系列的第一篇文章,我第一次写这样连续系列的文章,我先一层一层的剥开 Glide ,如果谁有更好的想法欢迎提出。

需知:本篇没有贴出太多 Glide 代码来对照分析,只是一个最简单的流程

看完这篇文章你会得到什么:
这篇文章你将会看到 Glide 的基本运作流程


Glide 的基本用法 整篇文章都是按照此代码环境来讲解的

Glide.with(Activity).load(Url).into(ImageView);

各个流程对象的转换

首先我先说一下 Glide 在各个流程上对象的转换

  1. 首先调用 with() 方法 会返回 RequestManager 这个对象

  2. 然后调用 load() 此时会返回 DrawableTypeRequest 对象,但是这个地方要注意了 这个对象继承自 GenericRequestBuilder 对象,从词义上来看
    这个对象是生成『通用请求生成器』,其实它的作用和他的词义其实一样的(不得不给 Glide 作者点个赞)

  3. 然后调用 init() 方法会构建 ViewTarget 然后开始获取资源,缓存,读取缓存,变换等处理然后放在 ImageView 上面

具体分析每个步骤所做的事情

具体分析每个以下每个步骤

with 方法

这个方法主要是往当前 Activity 里面添加 Fragment 并注册生命周期监听器,构建 RequestManager 、如果 Glide 没有初始化,也会初始化 Glide (RequestManager 这个地方要注意了,这个对象是一个 Activity 会有一个 RequestManager 对象,他不是单例的,为什么呢可以去看源码)

  1. with() 这个方法有好几个重载、但是呢...不用管他、他无论传成什么都是干的一个事我就随便挑一个说了with(FragmentActivity activity),在方法里面调用 RequestManagerRetriever.get() 会获取 RequestManagerRetriever (这个类的作用是提供 RequestManager)的单例,然后调用 RequestManagerRetriever.get() 方法,获取 FragmentActivity 中的 FragmentManager 对象(不同的方法可能获取方法不同,这里我们直说这一种,其他的可以自己去看一下源码),然后把 SupportRequestManagerFragment 加入到当前的 Activity 中(添加这个 Fragment 的目的是为了监听当前 Activity 的生命周期、这里监听生命周期的作用是及时取消图片资源获取,转换的任务,以防止性能上的浪费),然后把 Fragment 的监听器取出来,构造出 RequestManager ,再把 RequestManager 放到 Fragment 里面(后面几个方法我没有提名字,只提了实现了什么,你们看一下源码就会懂)

  2. 构造 RequestManager 的时候会获取单例的 Glide,如果 Glide 没有初始化 他会通过 GlideBuilder 来构建 Glide 里面完成了一些 缓存、线程池、转换、资源获取以及转换的控制类 等等的东西,然后调用 new 出 Glide

  3. 在 Glide 的构造方法里 注册了一堆监听,以及类的提供者,注册不同类型的
    ModelLoader ,注册变换的类等等(这个方法好多东西我还不知道是干什么的 我搞清了会更新博客)

  4. 然后他就会读取 Manifest 的里面 value 为 “ GlideModule” 的所有 meta-data 标签,然后获取 key 通过反射的方式获取 GlideModule,然后调用 GlideModule.registerComponents() 方法,将 ModelLoader 注册进 Glide 并且替换掉相同类型的 ModelLoader (为什么会讲是会替换掉相同类型的 ModelLoader 呢,因为 load() 有好多重载,它是根据类型把不同类型的 ModelLoader 放到一个 Map 里供,解析使用,具体到 into 再细说),通过这种方式我们就能够在外部提供自己的解析器了

  5. ConnectivityMonitor 来判断有没有网络状态获取的权限 然后选择往 Fragment 的监听器里面放网络监听器,还是空监听器,如果当前 APP 有获取网络状态的权限,他就会在网络改变的时候,调用任务队列,会重新启动任务

load 方法 此处分析的是传入 String 参数 并且是个 URL 地址

这个方法主要功能是根据传入的参数类型返回相应的 ModelLoader ,维护请求队列、 Activity 生命周期监听器、等、并构建 DrawableTypeRequest 对象

1. 在fromString() 中调用 RequestManager.loadGeneric(Class<T> modelClass) 方法来获取 GenericRequestBuilder<T> 类,那么这个方法干了什么呢。
  1. 首先调用 Glide.buildStreamModelLoader() 方法,然后在方法里调用 buildModelLoader(modelClass, InputStream.class, context),再在方法里调用Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass) 他会现在 Glide 中获取 ModelLoader 的工厂(GenericLoaderFactory 这个类里面保存有 完整的 ModelLoader 列表,和缓存的 ModelLoader,这个类是在 Glide 的构造方法中 new 出来的,跟随 Glide 为单例),获取之后调用工厂的 buildModelLoader() 的方法,在这个方法中他首先获取 缓存的 ModelLoader 如果没有就读取整个 ModelLoader 列表来获取 ModelLoader,并且把这个 ModelLoader 缓存起来,以后再用的时候就可以快速读取
  2. 调用Glide.buildFileDescriptorModelLoader(modelClass, context) 方法,然后在这个方法里调用了 buildModelLoader(modelClass, ParcelFileDescriptor.class, context) 和上个步骤一样的方法,并传入了一个类型,具体就不多说了,流程一样
  3. 第三步他会构建出 new 出 DrawableTypeRequest 对象
2. loadGeneric() 调用完,回到 load 方法哪里他会调用 DrawableRequestBuilder 的 load(ModelType model) 方法,把泛型参数储存一下,在我们的分析环境下就是 String 类型的,到此为止 DrawableTypeRequest 就构建出来了,他是继承自 DrawableRequestBuilder 也继承自 GenericRequestBuilder,下一个步骤就密切和 这个类相关了

into 方法

这个方法比较重要

  1. 调用 into(ImageView view) 方法,他会先判断图片显示方式然后设置不同的变换,然后先调用 buildImageViewTarge() 方法,在方法里面再调用 ImageViewTargetFactory.buildTarget(Class<Z> clazz) 方法来生成 ViewTarget(ImageViewTargetFactory 类也是在 Glide 初始化的时候就生成了,在 buildTarget() 方法中的 clazz 参数是在 DrawableTypeRequest 的父类 DrawableRequestBuilder 中的构造中传入的是 GlideDrawable.class ),所以这个 switch 语句 最终获取的也是 GlideDrawableImageViewTarget 类,这个类的构造也只是 存储的一下 View 此时先不必深究
  2. ViewTarget 构建完了然后调用into(Y target) 方法(Y extends Target<TranscodeType>),然后判断当前是否是主线程、如果不是那就要蹦沙卡拉卡了,然后在 TargetView 中获取 Request 如果有则停止并移除,通过 buildRequest() 方法获取 Request 然后添加到 ViewTarget 中,添加到 RequestTracker 队列中,以及监听中,这一步的源码我贴出来,看最下面
  3. 第三步将下面源码片段的 buildRequest(target) ,这个方法里面有个判断他的意思是,如果用户没有设定 Request 的线程优先级,就默认(这个地方 Glide 的默认线程优先级是低于 UI 线程的,他就是怕影响 UI 线程,如果没有特殊要求建议不要改动),然后调用 buildRequestRecursive() 这个方法,这个方法首先判断用户是否设置过加载的资源是图片的缩略图(低配版的图片),下面两个判断都是和缩略图有关系,如果就按照咱们上下文环境,也就是最简单的流程他走的是 else 调用 obtainRequest() 方法,在方法里再调用 GenericRequest.obtain() 来构建 GenericRequest ,构建的详细过程就不说了大家自己看一下
  4. 第四步 RequestTracker.runRequest(request) 从词义上来看就是开始请求,实际呢,你只要知道这个方法是运行 Request 就行了(这段代码简单,你简单看一下就行,RequestTracker 的作用是暂停、开始、暂停或重新运行任务,他是和 Fragment 生命周期有关联的),然后调用 Request.begin() 方法改变 Request 的 状态,然后调用 onSizeReady() 方法再次修改 Request 的状态,获取各种加载器,调用 Engine.load() (这个类以及方法的作用是控制缓存获取资源等任务,下一篇会详细讲),你会发现 load 方法里面有个回调接口,他传递的是 this,他会继续调用 target.onLoadStarted(getPlaceholderDrawable()); 这个方法可以点进去看一下功能,就是把占位的图片加载到 View 上,我们再返回去看 Engine.load() 里面,他加载成功的时候会回调 onResourceReady(Resource<?> resource) 方法,因为我们回调传的是 this 所以回调了 GenericRequest.onResourceReady() 他会把资源加载到 ImageView 上去(这里是简单说了一下流程,下一篇会详说)
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);

小结

我自己本身没有读过这种类型的库,我都是看的 github 上面用到的库,没事简单的看一看。说一下感想吧!我一开始想看 Glide 的时候有点怕,不知道如何下手也怕读不明白,就下载了源码去简单的看一看。我读的思路就是这个库的入门用法Glide.with(Activity).load(Url).into(ImageView);最简单的语句,就慢慢的一点点的看,看他是怎么转换的每个步骤怎么走的,如果理不清楚可以依靠 Debug 调试,跟着他走一遍,我也是看了好几遍才找到头绪。坚持才会赢嘛,网上都说他们读了两天就差不多了,咱比不了啊!看了四五天就稍微有个头绪,慢慢看吧,坚持就是胜利!!!

我的理解还是有点浅薄同时文章写的也不熟练,欢迎各位提出问题

目录
相关文章
|
4月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
133 2
Glide源码学习八:实现带进度的Glide图片加载功能
Glide源码学习八:实现带进度的Glide图片加载功能
|
3月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
36 0
|
容器
Flutter | 三棵树构建流程分析(上)
Flutter | 三棵树构建流程分析(上)
Flutter | 三棵树构建流程分析(上)
|
容器
Flutter | 三棵树构建流程分析(下)
Flutter | 三棵树构建流程分析(下)
Flutter | 三棵树构建流程分析(下)
|
缓存 存储
13.Glide源码分析1(生命周期关联)
Glide.with(mContext).load("baidu.com") .centerCrop().
1305 0
|
Java Android开发
【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(一)
Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(一)
273 0
|
Java Android开发
Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(二)
Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )(二)
293 0
|
Java Android开发
【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )
【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )
156 0
|
Shell 数据库 Android开发
【Android 性能优化】应用启动优化 ( 阶段总结 | Trace 文件分析及解决方案 | 源码分析梳理 | 设置主题的方案总结 ) ★
【Android 性能优化】应用启动优化 ( 阶段总结 | Trace 文件分析及解决方案 | 源码分析梳理 | 设置主题的方案总结 ) ★
285 0