Glide 流程分析

Glide(4.6.1)

简介

bumptech开发,多款Google应用使用

优点
  1. 组件生命周期绑定,防止内存泄漏
  2. 多种原始数据加载(asset,网络,byte[],流),同时支持Volley,Okhttp;默认使用HttpURLConnection实现网络—参见DataFetcher
  3. 支持gif,可以扩展支持svg,支持视频快照
  4. 内部多面向接口编程,容易扩展
  5. 注册进程低内存回调,可以释放内存,降低OOM风险
缺点
整体结构

uml.png

关键类
  1. Glide
    使用入口
  2. Engine
    加载引擎
调用流程
基本使用

Glide.with(context).load(url).into(ImageView)

以上述使用方式为例,解析整个流程,其中包括RequestManger的获取,资源的获取,解析,和最好的回调设置
涉及的关键类有:

  1. RequestManager
    glide中管理,启动请求的类,可以使用Activity,Fragment来绑定声明周期,自动关联定制,开始,重启请求
  2. RequestBuilder
    通用的请求构建类,可以对所有的资源类型设置参数,开始加载
  3. RequestTracker
    对于完成,失败的请求进行记录,取消,重启(非线程安全,只在主线程中使用)
  4. Target(Interface)
    资源加载的目标,并且绑定相关声明周期;如果在内存中,或者通过空的model进行加载时,不会回调onLoadStarted方法,其实现类较多,如常用的ImageViewTarget
  5. Request(Interface)
    为Target加载资源的请求类,其实现类有:

    • ErrorRequestCoordinator
    • SingleRequest
    • ThumbnailRequestCoordinator
  6. Engine
    负责启动加载和管理active和cached资源

  7. EngineJob
    对加载行为进行监听,并在完成时通过Handler进行线程转换

  8. DecodeJob
    负责解析原始资

  9. DataFetcherGenerator(Interface)
    根据原始资源的不同,生成对应的DataFetcher,并触发DataFetcher的loadData()方法,其实现类有:

    • DataCacheGenerator
    • ResourceCacheGenerator
    • SourceGenerator
  10. DataFetcher(Interface)
    将原始资源加载但内存中,实现类加多:

    • AssetPathFetcher
    • HttpUrlFetcher
    • OkhttpStreamFetcher
    • VolleyStreamFetcher

into.png

简单解析

  1. 整个流程的入口为Glide的with()方法,改方法的参数重载有Context,FragmentActivity,Activity三种,内部通过参数的不同的实例类型(使用不同类型的Lifecycle和RequestManagerTreeNode)获取RequestManager
  2. 每个RequestManager通过RequestManagerFactory构建,然后使用load方法获取RequestBuilder对象;load方法接收byte[],URL,Integer(resourceId),File,Uri,Drawable,Bitmap,String几种参数类型,每个类型的缓存策略不同,如Bitmap就不需要进行磁盘缓存;
  3. 通过load方法获取RequestBuilder对象后,可以直接通过into()方法,将目标容器可以设置为对应的ImageView,其会转化为ImageViewTarget;into()方法也可以接收Target类型参数(Target接口定义了资源加载的事件回调)
  4. 最终调用三个参数的into()方法后,由之前的RequestManager对象的track()方法发起Request对象的beigin()方法
  5. 以流程图中的SingleRequest为例,在该对象内的onSizeReady()方法中调用Engine的load()方法开始加载流程

    1. 首先验证是否存在于ActiveResources中,存在则进行回调,流程完毕
    2. 验证是否在MemoryCache中,此处采用remove()的方式获取资源对象EngineResource<>,存在则进行回调,流程完毕
    3. 验证是否在请求列表中,存在则添加回调,流程完毕
    4. 否则通过相关参数构建EngineJob,DecodeJob对象,并调用EngineJob的start()方法开始获取原始资源流程(此处包括本地磁盘和原始数据两层
  6. EngineJob内部根据参数选取适合的线程池(GlideExecutor),执行DecodeJob中的run方法(DecodeJob实现了Runnable)
  7. 根据不同的阶段进行后续操作,会在适合的阶段调用DataFetcherGenertor的startNext()方法,并在该方法中有限获取本地磁盘缓存
  8. 在startNext()方法中调用DataFetcher中loadData()方法,该方法会读取数据到内存(如网络,磁盘,asset等),并在完成后对结果回调至DecodeJob中
  9. 后续会涉及到LoadPath,DecodePath,ResourceTranscoder等一系列操作
  10. 在最后返回Resource后,将该资源缓存到ActiveResources中,在当前正在执行的任务队列中Jobs中移除;将Resource回调至SingleRequest中,最终回调Target的onResourceReady()方法
  11. 以ImageViewTarget为例,进行资源设置和执行动画

note:流程图中缺少上述9步,分析时略过

注意事项

  1. 由于Glide.with()内通过使用FragmentManager/SupportFragmentManager操作Fragment实现的生命周期的绑定,所以对调用线程有验证,只有在主线程中调用时才有效,非主线程中调用时会使用ApplicationContext进行操作,并且声明周期无关
  2. EngineResource的每个对象进行引用计数,在release()中及时释放内存其他引用对象
  3. 三个缓存容器,按优先级ActiveResources > MemoryCache > LazyDiskCacheProvider
  4. 在Engine内部包括原始数据(sourceExecutor)和磁盘数据(disCacheExecutor)两种线程池,初始化位于GlideBuidler(还包括一个动画线程池(animationExecutor))中,上述的线程池为glide中的自定义线程池GlideExecutor
  5. 使用了大量的对象池技术,如GlideBuilder中的BitmapPool、ArrayPool等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值