图解Glide流程

   在这一周的时间内,事情不是太多,简单的阅读了下Glide 3.6.1的源码,对于其整个调用流程有了一定的了解,希望通过本篇将其总结下来,一来加深印象,二来以后可以反复修改。主要想通过时序图分享一下Glide的调用流程以及其中比较关键的生命周期管理和数据处理流程。

一、流程分析

在整个分析的过程中都基于

Glide.with(context).load(“”).asBitmap().into(imageView)

这一条简单的Glide的使用,了解背后的机制

以下是在在这个上述调用中的整个流程的时序图


分析流程主要分为四部分:

1、初始化:加载库中已经注册的和用户在Manifest文件中注册的数据、建立生命周期的回调以及资源回调

2、Request创建

3、Request调度:解析缓存资源

4、资源回调:资源解析完毕后,将其加载到与之对应的Target中

1.1 初始化

      初始化过程包括各种数据的预加载,以及生命周期的绑定和各种回调接口的设置。

    1、其中为了方便使用,因为DataLoadProvider关联三个类型、ModuleLoader通DataLoadProvinderRegistry建立 dataClass 、sourceClass、DataLoadProvinder之间的映射关系通过TranscoderRegistry 建立 decodedClass 与transcoderClass 之间的管理,方便之后的使用。不过,存在一个小问题是,在初始化的时候注册了太多与当前项目无关的数据,不过为了通用,这个是不可避免的了。

    2、通过无界面的Fragment将当前Context 下所对应的LifeCycleListener对应的生命周期与当前Context的生命周期绑定在一起 ,从而可以动态调整request、网络状态监听等

1.1.1 时序图


(时序图比较大,看的不是很清楚)

1.1.2 详细类

Glide 

     框架的入口类,提供了各种静态方法来创建request管理engine 、BitmapPool、DiskCacke、MemoryCacheGlideBuilder  给Glide设置一些默认配置,从而更方便创建Glide,可以认为是Builder Pattern,将构造函数分解为:先设置属性,然后创建

GlideModule

    允许Glide使用GlideBuilder延迟加载一些配置选项和ModelLoader的注册,当编写一个Module之后,需要在AndroidManefist.xml中meda-data配置,然后使用的时候通过 ManifestParser解析反射使用

    注意:1、所有的实现module必须是Public,拥有一个空的构造函数,以便Glide通过反射来懒加载

    2、GlideModule的调用注册是随机的,因此在创建多个GlideModule时,要注意不同Module之间的setting不要产生冲突。如果应用依赖已经有冲突的libraries,应该考虑将在单一的Application Module中注册。

DataloadProviderRegistry  

        考虑到DataLoadProvider 关联两个指定的Data、Resource类型,所以在应用初始化的时候,就将使用到的DataLoadProvider与之相关联的两个类绑定在一起(注册),然后使用的时候根据需要转换的两个类型来获取对应的DataLoadProvider来decode(解析) 、encode(缓存)

TranscoderRegistry

       与DataLoadProviderRegistry 类似,只不过注册的是 从A转换到B,与之使用到的资源解析类型三个类之间的关系 

GenericLoaderFactory  

ManifestParser  

      解析在AndroidManifest中使用到的GlideModule然后反射使用

RequestManager

    管理、启动requests,可使用Activity、Fragment、 Connectivity 等生命周期方法来管理和启动请求,主要实现方式是使用Fragment 作为媒介,将自定义的LifeCycle接口与这些生命周期管理绑定在一起(后续会详细介绍) 

1、任务调度,根据生命周期启动、暂停、终止系统中已有的任务

2、为RequestManagerFragment设置生命周期监听:任务监听、网络添加、图片动画监听(这个监听要延迟到Target创建成功才会创建,所以就要把lificycle传递)等

    注意:因为RequestManager是与Activity、Fragment等Context绑定在一起来管理request的,所以要使用尽量小的Context,避免使用Application等全局上下文,如果使用全局比较大的上下文,与其相关的Options会一直保存在内存中,所以可能 leak memory

RequestManagerTreeNode

    提供了可以访问当前上下文中所有的RequestManager,也就是说基于Context层次结构建立了RequestManager的层次结构,而上下文的层次结构是在Activity / Fragment中嵌套的。不过,注意,如果当前上下文是Application Context ,只能访问当前上下文的RequestManager. 总而言之就是更方便的管理所有的RequestManager 。

RequestManagerRetriever

     可用来创建RequestManager或者从Activity和Fragment 中检索已经存在的RequestManager来重用

SupportRequestManagerFragment

     和RequestManagerFragment一样,都是一种Fragment,,只不过是没有任何界面信息,总关键的时可以用来管理RequestManager 的start、staop、管理request。更广泛的说法是可以储存实现了LifecycleListener 接口的对象(比如Fragment、ConnectivityMonitor),然后在Fragment 的生命周期方法中回调LifeCycle,从而将自定义的LifeCycle生命周期回调与当前Fragment所在的父Activity/Fragment 绑定在一起。

ConnectivityMonitor

    网络状态的监听接口,实现了LifecycleListener ,与Activity/Fragment 生命周期绑定在一起。具体实现DefaultConnectivityMonitor 以及NullConnectivityMonitor ,其中前者是一个网络监听的具体实现,后者是一个空实现,类似于Null Object Pattern ,可以避免空指针异常

ActivityFragmentLifecycle

    一个LifeCycle接口的具体实现,可用来在在Fragment 的生命周期方法中跟踪、通知LifecycleListener。

1.2 Request创建

     当RequestBuilder创建好之后,就可以创建request,来发起请求,在Into这个方法中,首先创建了 ViewTarget来封装View,从而可以在其周围添加相关的生命周期回调方法,可以在图片请求到时进行设置,然后就是创建Request,并将request相关信息保存在 ViewTarget,从而达到重用的目的。当Request创建好之后,就可以通过RequestTarcker来调度发起请求,当获取请求是则进入下一步

1.2.1 时序图


Engine

 Responsible for starting loads and managing active and cached resources.

    Start load 

实现了各个资源回调,用于管理磁盘、内存中的缓存资源


主要方法:

Load():

Starts a load for the given arguments .必须在主线程中调用。

调用流程主要分为两部分:

1、获取缓存的EngineResource:分别从缓存、内存活态中获取

2、EngineJob调度新的任务:

从jobs池中获取

创建新的EngineJob

             详细操作流程如下所示:



EngineJob

介于Engine. EngineRunnable之间,主要用于管理各种ResourceCallBack,根据EngineResource加载的各种状态来通知其余相关的ResourceCallBack以及EngineJobListener。


EngineRunnable

单独开启一个后台Thread 解析资源,解析流程和加载缓存流程相反,

1、分别查看缓存中已经转换的资源和转换之前的资源

2、使用资源的源重新加载缓存

其中EngineRunnable中包括一个接口:

EngineRunnableManager在ResourceCallBack的基础上添加了新的方法:submitForSource(),因为EngineResource需要从缓存中加载,不仅包括加载成功、失败,而且当加载失败时需要重新请求获取资源。

Request

  请求封装类

RequestBuilder:


Request相应的创建类,由于Request需要太多的参数,在RequestBuilder中有了默认的参数,然后提供设置方法让用户自定义,从其继承结构可以看出,具体实现类BitmapTypeRequst给人的感觉更像Request而不是RequestBuilder,不晓得为何如此命名。


1.3 Request调度:解析资源

在解码过程中,就涉及到数据的传递,如何从最初始的字符串或者其他获取到最后的图片信息


主要过程包括  Decode 、Transform 、Transcode 三个过程

1、Decode:从原始数据(字符串)获取图片资源

2、Transform:根据自定义的属性来对获取的资源进行裁剪、转换,默认实现返回原始资源

3、Transcode :用于资源的格式转换,默认实现返回原始资源

其中在每一个过程中都包括一个encode过程,将每一步获取的资源进行缓存。详细的数据加载流程见后文。


1.3.1 时序图

Decode



Transform&Transcode:

1.3.2 详细类

DecodeJob

DataFetcher

ResourceDecoder:


Downsample:

ResourceTranscoder:


FitCenter:

TransformationUtils:

ResourceTranscoder:

1.4 资源回调

1.4.1 时序图

当资源从缓存或者从其他地方获取到时,则通过如下的流程逐步调用到Target ,将获取到的资源设置其中。





二、关键点分析

2.1 request生命周期

    Glide 中使用Fragment 作为媒介,将任务调度的LifeCycleListener与Activity/Fragment 的生命周期事件进行绑定,在当前Activity/Fragment中启动、暂停request请求,主要LifecycleListener的实现包括:RequestManager、Target以及ConnectivityMonitor(监听网络状态)而且,通过RequestManagerTreeNode来保存当前Context所对应的RequestManager来管理当前Context下的所有请求。

    在初始化的过程中,主要建立RequestManager、RequestManagerFragment、LifecycleListener之间的关系。

RequestManagerFragment 主要作用是在其生命周期方法中调用实现了LifecycleListener的各个监听的生命周期方法

  调度的图示如下:



2.2数据加载流程

从网络请求图片这个过程,来说明在整个过程中的数据加载流



从url加载图片这个过程中来分析整个过程,考虑到了如下的问题:

1、如何获取Url?

2、解析到图片之后是否需要其他处理?

所以主要分为三部分:

请求前:根据提供的信息获取真正的数据源(InputStream)

请求;

请求后:图片格式转换

从而可以看出,在Glide中将这整个过程划分的很细致,每一部分都可以重写自定义

从中可以看出从“脏数据”到真正需要的图片所需要的整个过程。Model可以视为“脏数据”(待处理的数据源),ModelLoader


其中需要考虑请求网络图片的url如何获取,获取到的图片是否需要转换、转码

备注:

Model :“脏数据”(待处理的数据源)

ModelLoader中将“脏数据源”转换为真正的数据源,比如将 String——>InputStream 当把ModelType视作脏数据时,其实就是把ModelLoader看做成了判断、转换、预处理的过程。在脏数据与数据源之间就可以添加一个预处理操作,可以进行一些额外的限制(url长度限制)、数据格式转换:比如如下这个案例,在这个实例中,需要根据文件Id来获取图片资源,所以文件Id可以看做脏数据,也叫做待处理的数据源,通过重写ModelLoader,将脏数据转换成数据源,其中可以添加两个网络请求,来获取真正获取图片的InputStream

,其中http://www.licheedev.com/2015/09/19/custom-glide-modelloader/     在这个案例中,请求图片并不是给了url,而是根据id从服务器请求url,所以加载一次图片,得请求两次服务器,所以,一种可以采纳的策略是重写ModelLoader,传入id ,在其中进行一次网络请求,获取真正的InputStream ,从而充分利用了Glide。

Data:数据源(真正的数据源 InputStream)

Decode:进行一次网络请求,解析资源获取图片通过DataLoadProvinder的,其中提供了两个encode的缓存操作,其一是对数据源、另一个是对图片源缓存

Resource:图片源(从网络请求的图片)

Transform:转换图片(对图片进行裁剪等转换)

Transcode:对图片进行格式转换

Encode:缓存图片到本地



从数据处理的过程中就可以看出,Glide将图片加载从源头到图片都分布完成了,更方便的自定义操作,通过 ModelLoader、DataLoadProvinder、ResourceDecoder、Encoder之间的交互,将整个流程连接起来。

总结下来:

ModelLoader:加载数据预处理,校验、转换操作

DataLoadProvinder:从数据源获取数据,提供了数据源和请求数据的缓存操作的封装




参考:

1、自定义ModelLoaderDataFetcher获取网络图片

http://www.licheedev.com/2015/09/19/custom-glide-modelloader/


2Downloadin-custom-sizes-with-Glide

https://github.com/bumptech/glide/wiki/Downloading-custom-sizes-with-Glide


3Google推荐的图片加载库Glide介绍

http://blog.csdn.net/jianghejie123/article/details/44725649


4Glide详解

     http://blog.csdn.net/xx326664162/article/details/50373676


     5、图片加载框架Glide解析

    http://blog.csdn.net/u011228356/article/details/45026431



  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值