这篇文章上次修改于 2136 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
转载请标明地址 QuincySx: http://www.jianshu.com/p/cf8f8f90f621
这篇文章是这个系列的第一篇文章,我第一次写这样连续系列的文章,我先一层一层的剥开 Glide ,如果谁有更好的想法欢迎提出。
需知:本篇没有贴出太多 Glide 代码来对照分析,只是一个最简单的流程
看完这篇文章你会得到什么:
这篇文章你将会看到 Glide 的基本运作流程
Glide 的基本用法 整篇文章都是按照此代码环境来讲解的
Glide.with(Activity).load(Url).into(ImageView);
各个流程对象的转换
首先我先说一下 Glide 在各个流程上对象的转换
- 首先调用 with() 方法 会返回 RequestManager 这个对象
- 然后调用 load() 此时会返回 DrawableTypeRequest 对象,但是这个地方要注意了 这个对象继承自 GenericRequestBuilder 对象,从词义上来看
这个对象是生成『通用请求生成器』,其实它的作用和他的词义其实一样的(不得不给 Glide 作者点个赞) - 然后调用 init() 方法会构建 ViewTarget 然后开始获取资源,缓存,读取缓存,变换等处理然后放在 ImageView 上面
具体分析每个步骤所做的事情
具体分析每个以下每个步骤
with 方法
这个方法主要是往当前 Activity 里面添加 Fragment 并注册生命周期监听器,构建 RequestManager 、如果 Glide 没有初始化,也会初始化 Glide (RequestManager 这个地方要注意了,这个对象是一个 Activity 会有一个 RequestManager 对象,他不是单例的,为什么呢可以去看源码)
- with() 这个方法有好几个重载、但是呢...不用管他、他无论传成什么都是干的一个事我就随便挑一个说了
with(FragmentActivity activity)
,在方法里面调用RequestManagerRetriever.get()
会获取 RequestManagerRetriever (这个类的作用是提供 RequestManager)的单例,然后调用RequestManagerRetriever.get()
方法,获取 FragmentActivity 中的 FragmentManager 对象(不同的方法可能获取方法不同,这里我们直说这一种,其他的可以自己去看一下源码),然后把 SupportRequestManagerFragment 加入到当前的 Activity 中(添加这个 Fragment 的目的是为了监听当前 Activity 的生命周期、这里监听生命周期的作用是及时取消图片资源获取,转换的任务,以防止性能上的浪费),然后把 Fragment 的监听器取出来,构造出 RequestManager ,再把 RequestManager 放到 Fragment 里面(后面几个方法我没有提名字,只提了实现了什么,你们看一下源码就会懂) - 构造 RequestManager 的时候会获取单例的 Glide,如果 Glide 没有初始化 他会通过 GlideBuilder 来构建 Glide 里面完成了一些 缓存、线程池、转换、资源获取以及转换的控制类 等等的东西,然后调用 new 出 Glide
- 在 Glide 的构造方法里 注册了一堆监听,以及类的提供者,注册不同类型的
ModelLoader ,注册变换的类等等(这个方法好多东西我还不知道是干什么的 我搞清了会更新博客) - 然后他就会读取 Manifest 的里面 value 为 “ GlideModule” 的所有 meta-data 标签,然后获取 key 通过反射的方式获取 GlideModule,然后调用
GlideModule.registerComponents()
方法,将 ModelLoader 注册进 Glide 并且替换掉相同类型的 ModelLoader (为什么会讲是会替换掉相同类型的 ModelLoader 呢,因为 load() 有好多重载,它是根据类型把不同类型的 ModelLoader 放到一个 Map 里供,解析使用,具体到 into 再细说),通过这种方式我们就能够在外部提供自己的解析器了 - ConnectivityMonitor 来判断有没有网络状态获取的权限 然后选择往 Fragment 的监听器里面放网络监听器,还是空监听器,如果当前 APP 有获取网络状态的权限,他就会在网络改变的时候,调用任务队列,会重新启动任务
load 方法 此处分析的是传入 String 参数 并且是个 URL 地址
这个方法主要功能是根据传入的参数类型返回相应的 ModelLoader ,维护请求队列、 Activity 生命周期监听器、等、并构建 DrawableTypeRequest 对象
1. 在fromString()
中调用 RequestManager.loadGeneric(Class<T> modelClass)
方法来获取 GenericRequestBuilder<T>
类,那么这个方法干了什么呢。
- 首先调用
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 缓存起来,以后再用的时候就可以快速读取
- 调用
Glide.buildFileDescriptorModelLoader(modelClass, context)
方法,然后在这个方法里调用了buildModelLoader(modelClass, ParcelFileDescriptor.class, context)
和上个步骤一样的方法,并传入了一个类型,具体就不多说了,流程一样
- 第三步他会构建出 new 出 DrawableTypeRequest 对象
2. loadGeneric() 调用完,回到 load 方法哪里他会调用 DrawableRequestBuilder 的 load(ModelType model)
方法,把泛型参数储存一下,在我们的分析环境下就是 String 类型的,到此为止 DrawableTypeRequest 就构建出来了,他是继承自 DrawableRequestBuilder 也继承自 GenericRequestBuilder,下一个步骤就密切和 这个类相关了
into 方法
这个方法比较重要
- 调用 into(ImageView view) 方法,他会先判断图片显示方式然后设置不同的变换,然后先调用
buildImageViewTarge()
方法,在方法里面再调用 ImageViewTargetFactory.buildTarget(Classclazz) 方法来生成 ViewTarget(ImageViewTargetFactory 类也是在 Glide 初始化的时候就生成了,在 buildTarget() 方法中的 clazz 参数是在 DrawableTypeRequest 的父类 DrawableRequestBuilder 中的构造中传入的是 GlideDrawable.class ),所以这个 switch 语句 最终获取的也是 GlideDrawableImageViewTarget 类,这个类的构造也只是 存储的一下 View 此时先不必深究 - ViewTarget 构建完了然后调用
into(Y target)
方法(Y extends Target) ,然后判断当前是否是主线程、如果不是那就要蹦沙卡拉卡了,然后在 TargetView 中获取 Request 如果有则停止并移除,通过buildRequest()
方法获取 Request 然后添加到 ViewTarget 中,添加到 RequestTracker 队列中,以及监听中,这一步的源码我贴出来,看最下面 - 第三步将下面源码片段的
buildRequest(target)
,这个方法里面有个判断他的意思是,如果用户没有设定 Request 的线程优先级,就默认(这个地方 Glide 的默认线程优先级是低于 UI 线程的,他就是怕影响 UI 线程,如果没有特殊要求建议不要改动),然后调用buildRequestRecursive()
这个方法,这个方法首先判断用户是否设置过加载的资源是图片的缩略图(低配版的图片),下面两个判断都是和缩略图有关系,如果就按照咱们上下文环境,也就是最简单的流程他走的是 else 调用obtainRequest()
方法,在方法里再调用GenericRequest.obtain()
来构建 GenericRequest ,构建的详细过程就不说了大家自己看一下 - 第四步
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 调试,跟着他走一遍,我也是看了好几遍才找到头绪。坚持才会赢嘛,网上都说他们读了两天就差不多了,咱比不了啊!看了四五天就稍微有个头绪,慢慢看吧,坚持就是胜利!!!
我的理解还是有点浅薄同时文章写的也不熟练,欢迎各位提出问题
没有评论