深入探索Glide图片加载框架:做了哪些优化?如何管理生命周期?怎么做大图加载?

您所在的位置:网站首页 glide加载图片优化 深入探索Glide图片加载框架:做了哪些优化?如何管理生命周期?怎么做大图加载?

深入探索Glide图片加载框架:做了哪些优化?如何管理生命周期?怎么做大图加载?

2024-07-17 10:11| 来源: 网络整理| 查看: 265

前言

Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。 但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点. 本文以Glide做了哪些优化为切入点,介绍与学习Glide的源码与原理,如果对您有所帮助,欢迎点赞.

Glide做了哪些优化?

要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题? 1.图片下载是个耗时过程,我们首先需要考虑的就是图片缓存的问题 2.图片加载也是个耗内存的操作,很多OOM都是图片加载导致的,所以我们也要考虑内存优化问题 3.图片加载到一半,页面关闭了,图片加载也应该中止,这又牵扯到了生命周期管理的问题 4.还有就是图片加载框架是否支持大图加载?大图情况下会有什么问题?

以上就是我们提出的有关于Glide的几个问题了,这样我们可以轻松得出本文主要包括的内容 1.Glide图片加载的总体流程介绍 2.Glide缓存机制做了哪些优化? 3.Glide做了哪些内存优化? 4.Glide如何管理生命周期? 5.Glide怎么做大图加载?

下面就带着问题进入正文~

1.Glide图片加载总体流程介绍

在开始了解Glide具体做了哪些优化之前,我们先对Glide图片加载的总体流程做一个简单的介绍,让大家首先有个整体概念。 同时在后面对Glide做的优化具体发生在哪一步也可以方便的知道. 概括来说,图片加载包含封装,解析,下载,解码,变换,缓存,显示等操作,如下图所示:

1.封装参数:从指定来源,到输出结果,中间可能经历很多流程,所以第一件事就是封装参数,这些参数会贯穿整个过程;2.解析路径:图片的来源有多种,格式也不尽相同,需要规范化;3.读取缓存:为了减少计算,通常都会做缓存;同样的请求,从缓存中取图片(Bitmap)即可;4.查找文件/下载文件:如果是本地的文件,直接解码即可;如果是网络图片,需要先下载;5.解码:这一步是整个过程中最复杂的步骤之一,有不少细节;6.变换:解码出Bitmap之后,可能还需要做一些变换处理(圆角,滤镜等);7.缓存:得到最终bitmap之后,可以缓存起来,以便下次请求时直接取结果;8.显示:显示结果,可能需要做些动画(淡入动画,crossFade等)。 2.Glide缓存机制做了哪些优化?

我们知道,下载图片是非常耗费资源的,所以图片缓存机制是图片加载框架很重要的一部分,下面就以一张表格来说明下 Glide 缓存。

缓存类型缓存代表说明活动缓存ActiveResources如果当前对应的图片资源是从内存缓存中获取的,那么会将这个图片存储到活动资源中。内存缓存LruResourceCache图片解析完成并最近被加载过,则放入内存中磁盘缓存-资源类型DiskLruCacheWrapper被解码后的图片写入磁盘文件中磁盘缓存-原始数据DiskLruCacheWrapper网络请求成功后将原始数据在磁盘中缓存

在介绍具体缓存前,先来看一张加载缓存执行顺序,有个大概的印象

Glide的缓存机制,主要分为2种缓存,一种是内存缓存,一种是磁盘缓存。 之所以使用内存缓存的原因是:防止应用重复将图片读入到内存,造成内存资源浪费。 之所以使用磁盘缓存的原因是:防止应用重复的从网络或者其他地方下载和读取数据。 正式因为有着这两种缓存的结合,才构成了Glide极佳的缓存效果。

2.1 内存缓存

Glide默认开启内存缓存,我们也可以通过skipMemoryCache关闭 上面我们可以看到内存缓存其实分两个部分,ActiveResource缓存与LRU缓存 ActiveResources 就是一个弱引用的 HashMap ,用来缓存正在使用中的图片,使用 ActiveResources 来缓存正在使用中的图片,可以保护这些图片不会被 LruCache 算法回收掉

内存缓存加载顺序如下: 1.根据图片地址,宽高,变换,签名等生成key 2.第一次加载没有获取到活动缓存。 3.接着加载内存资源缓存,先清理掉内存缓存,在添加进行活动缓存。 4.第二次加载活动缓存已经存在。 5.当前图片引用为 0 的时候,清理活动资源,并且添加进内存资源。 6.又回到了第一步,然后就这样环环相扣。

总结为流程图如下:

我们上面总结了Glide内存缓存加载的流程,看到这里我们很容易有个疑问,为什么Glide要设计两种内存缓存?

2.1.1 为什么设计两种内存缓存?

LruCache算法的实现,你会发现它其实是用一个Set来缓存对象的,每次内存超出缓存设定触发trim操作的时候,其实是对这个Set进行遍历,然后移除缓存。但是我们都知道Set是无序的,因此遍历的时候有可能会把正在使用的缓存给误伤了,我还在用着它呢就给移出去了。因此这个弱引用可能是对正在使用中的图片的一种保护,使用的时候先从LruCache里面移出去,用完了再把它重新加到缓存里面。

举个例子

比如我们 Lru 内存缓存 size 设置装 99 张图片,在滑动 RecycleView 的时候,如果刚刚滑动到 100 张,那么就会回收掉我们已经加载出来的第一张,这个时候如果返回滑动到第一张,会重新判断是否有内存缓存,如果没有就会重新开一个 Request 请求,很明显这里如果清理掉了第一张图片并不是我们要的效果。所以在从内存缓存中拿到资源数据的时候就主动添加到活动资源中,并且清理掉内存缓存中的资源。这么做很显然好处是 保护不想被回收掉的图片不被 LruCache 算法回收掉,充分利用了资源。

2.1.1 小结

本节主要总结了Glide内存缓存加载的流程 1.首先去获取活动缓存,如果加载到则直接返回,没有则进入下一步 2.接着去获取LRU缓存,在获取时会将其从LRU中删除并添加到活动缓存中 3.下次加载就可以直接加载活动缓存了 4.当图片引用为0时,会从活动缓存中清除并添加到LRU缓存中 5.之所以要设计两种内存缓存的原因是为了防止加载中的图片被LRU回收

2.2 磁盘缓存

首先了解一下磁盘缓存策略

DiskCacheStrategy.NONE: 表示不缓存任何内容。DiskCacheStrategy.RESOURCE: 在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源。DiskCacheStrategy.DATA: 在资源解码前将原始数据写入磁盘缓存。DiskCacheStrategy.ALL : 使用DATA和RESOURCE缓存远程数据,仅使用RESOURCE来缓存本地数据。DiskCacheStrategy.AUTOMATIC:它会尝试对本地和远程图片使用最佳的策略。当你加载远程数据时,AUTOMATIC 策略仅会存储未被你的加载过程修改过的原始数据,因为下载远程数据相比调整磁盘上已经存在的数据要昂贵得多。对于本地数据,AUTOMATIC 策略则会仅存储变换过的缩略图,因为即使你需要再次生成另一个尺寸或类型的图片,取回原始数据也很容易。默认使用这种缓存策略

在了解磁盘缓存时我们主要需要明确一个概念,是当我们使用 Glide 去加载一张图片的时候,Glide 默认并不会将原始图片展示出来,而是会对图片进行压缩和转换,总之就是经过种种一系列操作之后得到的图片,就叫转换过后的图片。 我们既可以缓存变换之前的原始图片,也可以缓存变换后的图片

2.2.1 为什么需要两种磁盘缓存

上文已经说了,DiskCacheStrategy.RESOURCE缓存的是变换后的资源,DiskCacheStrategy.DATA缓存的是变换前的资源 举个例子,同一张图片,我们先在100*100的View是展示,再在200*200的View上展示 如果不缓存变换后的类型相当于每次都要进行一次变换操作,如果不缓存原始数据则每次都要去重新下载数据 如下可以看出,两种缓存的key不一样

DiskCacheStrategy.RESOURCE currentKey = new ResourceCacheKey(helper.getArrayPool(),sourceId,helper.getSignature(),helper.getWidth(),helper.getHeight(),transformation,resourceClass,helper.getOptions()); DiskCacheStrategy.DATA DataCacheKey newOriginalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature()); 3.Glide做了哪些内存优化?

Glide的内存优化主要也是对Bitmap的优化,在回答这个问题前,我们可以想想有哪些常见的Bitmap优化手段 1.当图片大小与View大小不一致时,可以用inSampleSize进行尺寸优化 2.图片所占内存即宽高每像素所占内存大小,不同的模式每个像素所占的内存大小不同,我们可以利用inpreferredconfig配置 3.Bitmpa所占内存比较大,如果频繁创建回收Bitmap内存可能造成内存抖动,我们可以利用inBitmap利用Bitmap内存 4.内存缓存,上文我们已经介绍了Glide的弱引用缓存与LRU缓存

其实常见的Bitmap内存优化也就这么几种了,不过我们在工作中比较少直接使用他们。 下面我们就介绍下Glide中具体是怎么使用他们的.

3.1 尺寸优化

当装载图片的容器例如ImageView只有100*100,而图片的分辨率为800 * 800,这个时候将图片直接放置在容器上,很容易OOM,同时也是对图片和内存资源的一种浪费。当容器的宽高都很小于图片的宽高,其实就需要对图片进行尺寸上的压缩,将图片的分辨率调整为ImageView宽高的大小,一方面不会对图片的质量有影响,同时也可以很大程度上减少内存的占用

我们通常使用inSampleSize对Bitmap进行尺寸缩放

如果inSampleSize 设置的值大于1,则请求解码器对原始的bitmap进行子采样图像,然后返回较小的图片来减少内存的占用,例如inSampleSize == 4,则采样后的图像宽高为原图像的1/4,而像素值为原图的1/16,也就是说采样后的图像所占内存也为原图所占内存的1/16;当inSampleSize



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3