GLIDE原理

GLIDE原理,第1张

在glide中的with方法中,需要传入上下文,他底层都是调用的getretriever方法,当传入fragment的时候,通过fragmentgetactivity的activity的实例。getRetriever通过该方法获取了一个requestManagerRetriever实例,调用了get方法。传入的参数,获取到fragmentMannager通过这个得到requestManagerRetriever实例。Glide和页面的生命周期是绑定到一起的,可以感知调用页面的生命周期

Gilde和Picasso这个很相似,之前在加载的时候有导入过picasso,因为考虑内存的问题,就没有继续用这个东西了,

使用Gilde的方式:

Gildewith("上下文")load(String)into(imageview);

load是加载的地址,into是设置控件名称;

因为项目里面的群聊头像是后台拼接的,并且要用get请求方式获取,就是说,把请求地址作为的地址

Glidewith(getContext())load(Uriparse("你的请求地址"+ groupgetGroupId()))into(holderavatar);

写这个是为了为下次写群聊头像做铺垫,作为新手,一定要去看看Gilde这个框架,谷歌推荐使用的

查找缓存使用

用完移除

源码中查看EngineKey-----相当于key,算法序列abcdsxxfaskldfjklf

源码中查看Source-----相当于value(Bitmap),调用系统转换成Bitmap

情景: 相册类的App经常需要同时展示大量的,这种情况下的质量可以低一点,因为加载速度优先于的质量。

解决办法: 我们可以设置译码的格式,在RequestOptions中加入encodeFormat(BitmapCompressFormatWEBP)encodeQuality(10))的选项,①encodeFormat的参数有BitmapCompressFormatPNG,BitmapCompressFormatJPEG,BitmapCompressFormatWEBP(质量从高到低);②encodeQuality设置的是0-100的int类型,一个质量百分比参数,越小质量越低。

情景: 大体的意思应该是同一个URL在不同的时间可能会指向不同的资源,所以同样需要实时更新。

解决办法相同

情景: 开发一款有头像的APP,我们修改了头像并且更新到了服务端,可是当我们大图时加载出来的还是原来的头像。

解决办法: 这是Glide强大的缓存带来的副作用,我们可以在RequestOptions中加入diskCacheStrategy(DiskCacheStrategyNONE)skipMemoryCache(true)的选项。那么缓存的功能就会全部关闭,从而使得每次都是从服务端加载,所以头像会是最新。

情景: 省流量模式的应用情景就是减少不必要的加载。

解决办法: 我们可以在RequestOptions中加入onlyRetrieveFromCache(true)的选项。那么就只会从缓存中读取,如果没有缓存则不加载,从而达到减少流量消耗的目的。

优点

多样化媒体加载

Glide 不仅是一个缓存,它支持 Gif、WebP、缩略图。甚至是 Video

生命周期集成

通过设置绑定生命周期,我们可以更加高效的使用Glide提供的方式进行绑定,这样可以更好的让加载的请求的生命周期动态管理起来

高效的缓存策略

A 支持Memory和Disk缓存

B Picasso 只会缓存原始尺寸的,而 Glide 缓存的是多种规格,也就意味着 Glide 会根据你 ImageView 的大小来缓存相应大小的尺寸

比如你 ImageView 大小是200200,原图是 400400 ,而使用 Glide 就会缓存 200200 规格的图,而 Picasso 只会缓存 400400 规格的。这个改进就会导致 Glide 比 Picasso 加载的速度要快,毕竟少了每次裁剪重新渲染的过程,非常灵活 & 加载速度快

C 内存开销小

默认的 Bitmap 格式是 RGB_565 格式,而 Picasso 默认的是 ARGB_8888 格式,这个内存开销要小一半。

Android关于内存计算,共有四种,分别是:

ALPHA_8:每个像素占用1byte内存

ARGB_4444:每个像素占用2byte内存

ARGB_8888:每个像素占用4byte内存(默认,色彩最细腻=显示质量最高=占用的内存也最大)

RGB_565:每个像素占用2byte内存(8bit = 1byte)

举例说明:一个32位的PNG=ARGB_8888=1204x1024,那么占用空间是:1024x1024x(32/8) = 4,194,304kb=4M左右

在解析的时候,为了避免oom和节省内存,最好使用ARGB_4444模式(节省一半的内存空间)

42 缺点

使用方法复杂

由于Glide其功能强大,所以使用的方法非常多,其源码也相对的复杂

包较大

这里分两个部分:

ByteBufferWebpDecoder是最终webp动图资源解码器

先给出Glide加载webp动图的完整调用栈:

整个流程主要分三块:

load :通过RequestManager加载一个String 类型的model。

into:加载一个ImageView的目标控件作为target,然后通过RequestBuilder开始数据处理流程。

EngineJob以前的流程非常简单明确,这里着重看下DecodeJob部分的处理流程:

这里有个ModelLoader-LoadData-DataFetcher关系需要捋一下:

DecodeHelperjava

这里modelLoaders是在Registry中由ModelLoaderRegistry来获取所有的models。这里model对应ByteBufferFileLoader,由他执行buildLoadData。

ByteBufferFileLoaderjava

而LoadData是ModelLoader的内部类,它的属性包括一个DataFetcher,它就是最终加载数据的地方。

那么总结一下:首先是获取对应数据源类型的ModelLoader,ModelLoader初始化一个LoadData,然后LoadData通过内部关联的DataFetcher来正真去执行加载数据的 *** 作!

这里很显然对应的DataFetcher实例是LoadData初始化时传入的ByteBufferFetcher。回到SourceGenerator的startNext方法,最终调用ByteBufferFetcher的loadData。

当然这里数据获取的方式有很多种,有网络请求、有磁盘文件获取等等:

这里DataFetcher也可以自定义,举例:

Glide网络请求默认使用的是>

DecodeJob的主要工作是从磁盘或者数据源(比如网络)中获取资源,并进行转换和转码。

DecodeJob 实现了 Runnable 接口,它运行在 EngineJob 里面的线程池里。运行时首先会检查是否已经取消了执行,如果没有则执行 runWrapped()。

在 runWrapped() 中首先会判断当前的 runReason ,由于在 init() 中被赋值为 INITIALIZE ,则获取到的 stage 为 StageRESOURCE_CACHE ( Stage 表示当前执行到的阶段)。接着根据当前的 Stage 获取到的 DataFetcherGenerator 为 ResourceCacheGenerator,它用于从磁盘缓存中获取经过转化后的资源。不熟悉这个类的可以看下 Glide源码解析之ResourceCacheGenerator

获取到 DataFetcherGenerator 后就开始将获取数据的 *** 作交给它的 startNext() 来执行,这里我们以 ResourceCacheGenerator 成功获取为例,则 isStarted 会被赋值为 true ,不用进入循环。最终获取的数据会通过 DecodeJob 实现的 FetcherReadyCallback 的 onDataFetcherReady() 回调。

如果 ResourceCacheGenerator 没有获取到数据,由上可知则依次会交给 DataCacheGenerator (原数据的磁盘缓存) 和 SourceGenerator (从数据源加载,比如网络,不熟悉的可以看下 Glide源码解析之SourceGenerator )

在 ResourceCacheGenerator 加载数据成功后则通过 onDataFetcherReady() 回调给 DecodeJob ,由于 ResourceCacheGenerator 并没有切换线程去获取资源,所以会执行到 decodeFromRetrievedData() 去进行解码。经过一系列的调用,最终会将解码的 *** 作交给 LoadPath 去执行。

会遍历 decodePaths 来寻找哪个 DecodePath 是能完成解码工作的,而具体解码由分为三步,第一步为解码资源,第二步为解码之后的工作(实际为对资源进行缓存),第三步为转码,即是将获取到的资源类型转为另一种资源类型。

当资源类型是 ByteBuffer 的时候,对应的 DataRewinder 是 ByteBufferRewinder ,ResourceDecoder 是 ByteBufferBitmapDecoder ,则最终的解码 *** 作将由 ByteBufferBitmapDecoder 来完成。

首先会将 ByteBuffer 转化为 InputStream ,然后再交给 Downsampler来解码。

在解码 *** 作里首先会根据 Bitmap 的宽高和 ImageView 的宽高来计算出缩放值,然后从 BitmapPool 获取一个合适宽高的 Bitmap 交给 BitmapFactory 去进行最终的解码 *** 作,最后再判断是否需要对 Bitmap 进行旋转。

获取到 Bitmap 后将它包装进 BitmapResource 里返回,到此解码资源的工作就完成了。

解码资源完成后接着就轮到编码资源了,由 DecodeCallback (接口) 去执行,在 DecodeJob 的 runLoadPath() 中给callback 赋的值是 DecodeCallback (实现类),而它将具体的编码 *** 作又交回给了 DecodeJob 的 onResourceDecoded()去执行。

首先会判断资源是否可以编码,由上可知资源类型为 Bitmap ,是可以编码的。接着判断是否可以进行缓存,由于这里是从 ResourceCacheGenerator 获取数据的,本来就是从缓存中取得数据,所以不再需要进行缓存,最终会将源数据返回。

如果是需要缓存的则会交给 DeferredEncodeManager 进行磁盘缓存,如果对磁盘缓存不熟悉的可以看下 Glide源码解析之DiskCache

将 Resource<Bitmap> 传进 LazyBitmapDrawableResource ,而 LazyBitmapDrawableResource 有一个 get() 将 Resource<Bitmap> 转化为 BitmapDrawable 。到此数据的获取过程就结束了。

让我们回到 DecodeJob 一开始获取数据的时候,在获取到数据之后通过回调将数据传给 EngineJob 。接着如果需要缓存的则调用 deferredEncodeManager 去执行,最后释放资源。到此 DecodeJob 的使命就全部完成了。

以上就是关于GLIDE原理全部的内容,包括:GLIDE原理、Glide 图片库原理(三)缓存机制、glide优缺点等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/10160294.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存