Glide原理

KevinLau
8 min readApr 2, 2021

转载

version:4.12.0
https://github.com/bumptech/glide

相关类

  • Glide:Glide.initializeGlide初始化。
  • GlideBuilder:通过GlideBuilder.build创建Glide
  • RequestManager: 1. 绑定生命周期:在 Glide 中,一个 Context 对应一个 RequestManager,当我们调用 with() 方法时,RequestManager 会用对应的 Context 创建一个 RequestManagerFragment 。
    RequestManagerFragment 是一个无布局的 Fragment,主要是用来做生命周期关联的. 2.监听网络状态:RequestManager 中有一个网络连接监听器 RequestManagerConnectivityListener ,它实现了ConnectivityListener 接口,每次网络状态切换时,RequestManager 就会重启所有的图片加载请求。3.创建请求构建器 4.启动请求
  • RequestManagerRetriever:用来创建RequestManager。
    通过get方法根据不同的context进行创建。
    如果是Application,则创建根据ApplicationLifecycle的applicationManager
    如果是FragmentActivity,则通过supportFragmentGet。并创建SupportRequestManagerFragment
    如果是Activity,则通过fragmentGet。并创建RequestManagerFragment
    RequestManager:管理请求,根据生命周期事件处理。通过load方法创建RequestBuilder
  • GlideRequests:继承RequestManager,通过load返回GlideRequest
  • GlideExecutor:线程池。线程数量根据cpu数量最大4个
  • GlideRequest:继承RequestBuilder
  • RequestBuilder:构建请求。
  • ViewTarget:封装View
  • BaseRequestOptions:
    GlideContext:继承ContextWrapper
  • ImageViewTargetFactory:ViewTarget
  • SingleRequest:

加载时机:

我们经常在 Activity#onCreate 方法中直接使用 Glide 方法,但此时的图片大小还未确定,所以调用 Request#begin 时并不会直接发起请求,而是等待 ImageView 初始化完成,对于 ViewTarget 以及其子类来说,会注册View 的 OnPreDrawListener 事件,等待 View 初始化完成后就调用 SingleRequest#onSizeReady 方法,这个方法里就会开始加载图片了。

缓存机制

  • 活动资源Engine中的ActiveResources
    活动资源中是一个”引用计数"的图片资源的弱引用集合。使用一个 Map<Key, WeakReference<EngineResource<?>>> 来存储的
    EngineResourceacquired记录被引用次数
  • 内存缓存MemoryCache
    内存缓存默认使用LRU(缓存淘汰算法/最近最少使用算法)
    当资源从ActiveResources移除的时候,会加入此缓存。
    当资源从ActiveResources添加的时候,会移除此缓存。
    以上两点保证了 ActiveResource 和 MemoryCache 中的资源是不会有重复的
  • 磁盘缓存DiskCache
    资源类型缓存的是经过解码后的图片,如果再使用就不需要再去进行解码配置(BitmapFactory.Options),加快获得图片速度
  • 原始数据

缓存策略

  • DiskCacheStrategy.ALL:原始图片和转换过的图片都缓存
  • DiskCacheStrategy.RESOURCE:只缓存原始图片
  • DiskCacheStrategy.NONE:不缓存
  • DiskCacheStrategy.DATA:只缓存使用过的图片

生命周期管理

  • 传入一个ApplicationContext,Glide的生命周期就相当于绑定了整个应用,只要应用不退出,任何时候都能够加载,也可以理解为不对Glide生命周期进行管理。
  • 传入activity、FragmentActivity 、Fragment 及View ,这样就会创建一个看不见的fragment -> SupportRequestManagerFragment,Glide的生命周期就随着该Fragment的变化而变化。

CustomViewTarget 就针对这个问题给出了解决方案,其中会调用 View#addOnAttachStateChangeListener 方法添加一个监听器,这个监听器可以监听到 View 被添加到 Widow 以及移除 Window 时的事件,从而更好的管理 Request 生命周期。

通过Fragment的回调调用到Glide的RequestManager的对应的方法即可执行不同的操作,主要绑定的三个方法为:onStart(),onStop(),onDestroy()

列表加载问题

Glide在开始加载图片时,会给当前ViewTarget设置对应的Request,同时也会ViewTarget中的View设置tag为Request。在listView复用时有了这个Tag值,从而解决错乱的问题

切换到主线程:Handler

private static final Handler MAIN_THREAD_HANDLER =
new Handler(Looper.getMainLooper(), new MainThreadCallback());

线程池

public final class GlideBuilder {
...
private GlideExecutor sourceExecutor; //加载源文件的线程池,包括网络加载
private GlideExecutor diskCacheExecutor; //加载硬盘缓存的线程池
...
private GlideExecutor animationExecutor; //动画线程池

内存泄露

RequestManager onDestroy

清除缓存

ComponentCallbacks2的onTrimMemory

五种数据源Glide 中定义了下面 5 种数据源 DataSource。

  • LOCAL
    设备上有的数据,比如 App 内置的 Drawable 也属于 LOCAL ;
  • REMOTE
    从服务端拿到的数据;
  • DATA_DISK_CACHE
    从缓存中取出来的原始数据;
  • RESOURCE_DISK_CACHE
    从缓存中取出来的图片资源;
  • MEMORY_CACHE
    从内存缓存中取出来的数据;

使用

  • preload()
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.preload();
  • downloadOnly()

downloadOnly()方法表示只会下载图片,而不会对图片进行加载.

  • submit()

当图片下载完成之后,我们可以得到图片的存储路径,以便后续进行操作。

Glide的自定义模块扩展

https://www.jianshu.com/p/9190d0f08b66
可以实现下载或加载图片的进度

总结

整个运行中,只会存在一个Engine实例,一个ActiveResources,一个MemoryCache,若干个RequestManager,若干个Target与Request,一个Request中会持有一个其加载到的Resource。RequestManager与Target是与生命周期绑定的,在RequestManager中会根据生命周期方法调度其所有的Request对象,让它们取消或者重新加载。

转载:
https://juejin.cn/post/6882536990400020494
https://www.jianshu.com/p/9bb50924d42a
https://blog.csdn.net/hxl517116279/article/details/99639520
https://blog.csdn.net/guolin_blog/category_9268670.html
https://www.jianshu.com/p/d2e89a7380d7

--

--