2021-01-26

Glide实现原理解析

            一.Glide缓存机制

            

Glide采取的多级缓存机制,能够较为友好地实现图片、动图的加载。其主要有 内存缓存+磁盘缓存 ,当然他们的作用也有不同,其中内存缓存主要用于防止将重复的图读入内存中,磁盘缓存则用于防止从网络或者其他地方将重复下载和数据读取。

默认情况下,Glide 会在开始一个新的图片请求之前检查以下多级的缓存:

        1.活动资源 (Active Resources)

        2. 内存缓存 (Memory Cache)

        3.资源类型(Resource Disk Cache)

        4.原始数据 (Data Disk Cache)

活动资源:如果当前对应的图片资源正在使用,则这个图片会被Glide放入活动缓存。

内存缓存:如果图片最近被加载过,并且当前没有使用这个图片,则会被放入内存中

资源类型: 被解码后的图片写入磁盘文件中,解码的过程可能修改了图片的参数(如:inSampleSize。inPreferredConfig)

原始数据: 图片原始数据在磁盘中的缓存(从网络、文件中直接获得的原始数据)

在调用into之后,Glide会首先从Active Resources查找当前是否有对应的活跃图片,没有则查找内存缓存,没有则查找资源类型,没有则查找数据来源。

1.活动资源

活动资源中是一个”引用计数"的图片资源的弱引用集合。使用一个 Map>> 来存储的。

此外还有一个引用队列ReferenceQueue> resourceReferenceQueue;每当向 activeResource 中添加一个 WeakReference 对象时都会将 resourceReferenceQueue 和这个 WeakReference 关联起来,用来跟踪这个 WeakReference 的 gc,一旦这个弱引用被 gc 掉,就会将它从 activeResource 中移除。

2.内存缓存

内存缓存默认使用LRU(缓存淘汰算法/最近最少使用算法),当资源从活动资源移除的时候,会加入此缓存。使用图片的时候会主动从此缓存移除,加入活动资源。LRU在Android support-v4中提供了LruCache工具类。

3.磁盘缓存

资源类型缓存的是经过解码后的图片,如果再使用就不需要再去进行解码配置(BitmapFactory.Options),加快获得图片速度。比如原图是一个100x100的ARGB_8888图片,在首次使用的时候需要的是50x50的RGB_565图片,那么Resource将50x50 RGB_565缓存下来,再次使用此图片的时候就可以从 Resource 获得。不需要去计算inSampleSize(缩放因子)。

原始数据缓存的则是图像原始数据。


Glide

Glide.with(this).load(url).into(imageView);

三步走:先with(),再load(),最后into()

with()方法

是Glide类中的一组静态方法,

with()方法的重载种类非常多,既可以传入Activity,也可以传入Fragment或者是Context。每一个with()方法重载的代码都非常简单,都是先调用RequestManagerRetriever的静态get()方法得到一个

RequestManagerRetriever对象,这个静态get()方法就是一个单例实现,

然后再调用RequestManagerRetriever的实例get()方法,去获取RequestManager对象。

load()方法

参数类型:String,File,byte[],URL,图片资源ID,Uri,我这里只看参数类型为String类型的,这些方法都会返回DrawableTypeRequest对象。

image.png

load内部调用了fromString方法,fromString方法调用了loadGeneric方法,

loadGeneric()方法也没几行代码,这里分别调用了Glide.buildStreamModelLoader()方法和Glide.buildFileDescriptorModelLoader()方法来获得ModelLoader对象。

ModelLoader对象是用于加载图片的,而我们给load()方法传入不同类型的参数,这里也会得到不同的ModelLoader对象,最后返回一个DrawableTypeRequest对象。

DrawableTypeRequest的父类是DrawableRequestBuilder,

DrawableRequestBuilder中有很多个方法,这些方法其实就是Glide绝大多数的API了。里面有不少我们在上篇文章中已经用过了,比如说placeholder()方法、error()方法、diskCacheStrategy()方法、override()方法等,都是在DrawableRequestBuilder 类里面。提供了glide加载图片过程的很多方法

into()方法的作用:

①初始化各种参数,做好准备工作(网络请求、基于MVP的各种接口回调),②使用最原始的HTTPConnect网络连接,读取文件流,③根据文件判断是GIF动图还是Bitmap静态图片,④通过相关复杂逻辑将下载的图片资源取出来,赋值给ImageView控件。

Glide的核心思想:

对象池:

Glide原理的核心是为bitmap维护一个对象池。对象池的主要目的是通过减少大对象内存的分配以重用来提高性能。

生命周期绑定:

第一个with方法,这个其实就是一个工厂方法,虽然有许多重载的形式,其实都是要创建一个RequestManager对象。

创建一个透明的 RequestManagerFragment 加入到FragmentManager 之中

通过添加的这个 Fragment 感知 Activity 、Fragment 的生命周期。

图片的加载任务会与activity或者Fragment的生命周期绑定,当界面执行onStop的使用自动暂定,而当执行onStart的时候又会自动重新开启,同样的,动态Gif图的加载也是如此,以用来节省电量,同时Glide会对网络状态做监听,当网络状态发生改变时,会重启失败的任务,以减少任务因网络连接问题而失败的概率。


Bitmap复用池

如果缓存都不存在,那么会从源地址获得图片(网络/文件)。而在解析图片的时候会需要可以获得BitmapPool(复用池),达到复用的效果。复用并不能减少程序正在使用的内存大小。Bitmap复用,解决的是减少频繁申请内存带来的性能(抖动、碎片)问题。

BitmapPool是Glide中的Bitmap复用池,同样适用LRU来进行管理。在每次解析一张图片为Bitmap的时候(磁盘缓存、网络/文件)会从其BitmapPool中查找一个可被复用的Bitmap。当一个Bitmap从内存缓存 被动 的被移除(内存紧张、达到maxSize)的时候并不会被recycle。而是加入这个BitmapPool,只有从这个BitmapPool 被动的被移除的时候,Bitmap的内存才会真正被recycle释放。

二.Glide生命周期管理

Glide在Glide.with(context)中就实现了生命周期管理,with根据传入的参数有不同的实现。

//传入一个Context    public static RequestManager with(@NonNull Context context)

 //传入一个activity public static RequestManager with(@NonNull Activity activity)

  //传入一个FragmentActivity public static RequestManager with(@NonNull FragmentActivity activity) 

 //传入一个Fragment public static RequestManager with(@NonNull Fragment fragment) 

 //传入一个View public static RequestManager with(@NonNull View view)

虽然有这么多类型,但其实可以分为两类的。

传入一个ApplicationContext,Glide的生命周期就相当于绑定了整个应用,只要应用不退出,任何时候都能够加载,也可以理解为不对Glide生命周期进行管理。

传入activity、FragmentActivity 、Fragment 及View ,这样就会创建一个看不见的fragment,Glide的生命周期就随着该Fragment的变化而变化。


由于ActivityFragmentLifecycle对象是在fragment中创建并且它的onStart、onStop、onDestory方法与fragment一一对应,这样就将RequestManager的生命周期就与fragment关联起来了,也就与当前activity关联起来。总体流程如下:

当fragment生命周期发生变化时,通过ActivityFragmentLifecycle将变化告诉给RequestManager与DefaultConnectivityMonitor。而RequestManager又将此变化告诉给ImageViewTarget。

至于传入参数为其他类型的实现基本上与activity的类似,就不在叙述。

你可能感兴趣的:(2021-01-26)