android源码宇宙-Glide

描述

版本

源码基于4.12.0

    implementation 'com.github.bumptech.glide:glide:4.12.0'
    kapt 'com.github.bumptech.glide:compiler:4.11.0'
### glide使用
```kotlin
Glide.with(context)
    .load(url)
    .into(imageView);

源码

主流程分别是with、load、into这三个方法,我们重点分析一下

源码类图

在参考文章上找到了一张很棒的类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Z98swmB-1658542012976)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/48195adcd76a4c618dd381753c08a77a~tplv-k3u1fbpfcp-zoom-1.image)]

重要的方法和类

RequestManager

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Rbd7A9K-1658542012977)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5933ef5b08a74f42880ff56c342388dd~tplv-k3u1fbpfcp-zoom-1.image)]

RequestBuilder

这里可以这么看:
如果泛型类型是Bitmap,则会生成一个BitmapImageViewTarget
如果泛型类型是Drawable,则会生成一个DrawableImageViewTarget
这里的泛型对应的就是RequestBuilder.transcodeClass属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmXssbNa-1658542012978)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/400584f8e6d54e869764a5dd37de92d0~tplv-k3u1fbpfcp-zoom-1.image)]

with方法

  1. Glide.with重载参数

Glide的with方法可以使用如下图中的参数加载图片,所以我们可以知道Glide可以使用ApplicationContext、Activity、Fragment、View作为参数获取RequestManager

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9EG2Q3sA-1658542012979)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7bb4613c22564f22a2cbc4173c11653c~tplv-k3u1fbpfcp-zoom-1.image)]

  1. Glide.with

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FH1vWbJ7-1658542012980)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e966ebae94b84952915bcb427956b9d3~tplv-k3u1fbpfcp-zoom-1.image)]

  1. Glide.getRetriever方法获取RequestManagerRetriever

这里查看getRetriever和get方法

RequestManagerRetriever用来获取管理RequestManager,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hALpnhiu-1658542012980)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/be6aaf9ae7494210a3dc2e01200622b7~tplv-k3u1fbpfcp-zoom-1.image)]
get方法有五个重载方法,其中除了参数Context外,其它的都是使用Fragment实现的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pC20AwpD-1658542012981)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6f959ecfc5c146a18b1353c1a805100e~tplv-k3u1fbpfcp-zoom-1.image)]

Glide.with方法获取RequestManager方法

RequestManagerRetriever类的五个get方法后面讲解

小结

with方法内部会创建一个全局静态的glide对象
with方法主要的目的是返回一个RequestManager,并且with有五个重载方法,重载参数可以是Context、Fragment、ACtivity、View、FragmentActivity。最终会使用RequestManagerFactory.build方法创建RequestManager对象。

下面我们对with的几个重载参数进行一下说明,

  1. Activity:使用FragmentManager添加一个非v4的Fragment,然后调用fragmentGet方法,fragmentGet方法内部会创建RequestManager,并将RequestManager赋值给RequestManagerFragment,最后返回RequestManager。
  2. Fragment :使用Fragment添加一个子Fragment来实现,逻辑同1
  3. FragmentActivity:同1,不过添加的Fragment是v4的Fragment
  4. View:获取ApplicationContext,然后调用getApplicationManager来获取RequestManager,这种方式获取的RequestManager是不会管理Activity生命周期的
  5. Context:Context类型与1、2、3、4中哪个类型匹配就使用哪个类型来获取

load方法

  1. RequestManager.load方法

load方法也有多个参数的重载方法,方法返回RequestBuilder对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pKnXm8MU-1658542012981)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f9966e4698d4755ac9b7ab7b650cc71~tplv-k3u1fbpfcp-zoom-1.image)]

  1. RequestManager.asDrawable和RequestManager.load方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PkyJUxkD-1658542012982)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0ef05c78739e49ccb32550b0acae9b9b~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 查看asDrawable

asDrawable可以使用Drawable展示,还有几个方法asBitmap、asFile、asGif他们可以支持不同类型的图片加载

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4MZJEsSo-1658542012985)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e16ff3e22b174bdeac53c8af410699c6~tplv-k3u1fbpfcp-zoom-1.image)]

  1. RequestManager.as方法

这个as方法如下,返回一个RequestBuilder对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nG7hoVD9-1658542012985)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0d9ab0e744644b4aa50e30cb2fa5680f~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 上面获取RequuestBuilder.asDrawable还会调用load(url)方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zaBltVCO-1658542012986)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1028780679b1423ba926b14b3be8dbd8~tplv-k3u1fbpfcp-zoom-1.image)]
我们发现load方法到这里将url也就是loadGeneric方法的参数model赋值给了RequestBuilder.model
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJe9GyJ2-1658542012986)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/baddbbdeb6014b3981983a2c460e6638~tplv-k3u1fbpfcp-zoom-1.image)]

小结

RequestManager.load方法主要是用来决定我们要加载资源的类型,例如可能加载的是File、Bitmap、Drawable、Gif,然后生成一个RequestBuilder,并且将请求的url赋值给RequestBuilder.model。

into方法

非常长的方法

  1. RequestBuilder.into方法

这个tartet是在Glide中调用buildImageViewTarget方法生成的:
glideContext.buildImageViewTarget(view, transcodeClass)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuWEIefU-1658542012987)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bab5aedb494b4687b9246ac52fcb32bf~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 重载调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hh92qjDR-1658542012987)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a8e07e8971a14a798add809da0760311~tplv-k3u1fbpfcp-zoom-1.image)]

下面的target.setRequest方法最终将我们的request作为tag设置给了target内部持有的View,其实就是以前搞ListView的时候的view.setTag

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9S0IWniI-1658542012988)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a0cbb4037e4e466b9fe467039640d8d2~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7EkmF4lE-1658542012988)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/edb8b3dbdbd440d6afa12ba0d1ffb96f~tplv-k3u1fbpfcp-zoom-1.image)]

  1. RequestManager.track

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cB0Ff0dO-1658542012989)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d100b0bed79a4b0c8717f88bdefbe512~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 重点看第三步RequestTracker.runRequest方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fc9uZOIU-1658542012989)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8e6d8735f1794b36a6ecc87e152be687~tplv-k3u1fbpfcp-zoom-1.image)]

  1. Request.begin方法

我们主要看SingleRequest.begin方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-00DVZjmS-1658542012990)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9372cd6af3634bb4b232e79efcd705e8~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1e9817oW-1658542012990)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/559c5017ea35421a98cdfb0d49e84ff8~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 在SingleRequest.onSizeReady方法内部会使用engine加载图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6hJG6YPI-1658542012991)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/44b98373cacd405196ed37ed3f981395~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d6XjqX1N-1658542012991)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a4015be132d44a0086dbf47be61d8f44~tplv-k3u1fbpfcp-zoom-1.image)]

  1. Engine.load方法

后面的的方法使用waitForExistingOrStartNewJob加载图片资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lPbGDFYF-1658542012992)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d25787c952744324bad0f7ba633a9a5c~tplv-k3u1fbpfcp-zoom-1.image)]

  1. waitForExistingOrStartNewJob方法

engineJob.start(decodeJob);下图中这个方法是用来执行线程池获取图片资源的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NI3RTO3D-1658542012992)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b06727f00192465cbd8bddaf49fcb3c4~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kOjtFH5u-1658542012993)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dea98eb799f346669cc27f1ea3d4c7a8~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 实现线程池执行任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQL47PyY-1658542012993)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac73bb88e5b34028b45fe51e44f76038~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 线程池执行任务DecodeJob的run方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UOt65BWU-1658542012993)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c526af6bd0ea4c41885276b3388b88ac~tplv-k3u1fbpfcp-zoom-1.image)]

  1. DecodeJob.runWrapped方法

第二章图是getNextGenerator的代码说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CxY1yAgt-1658542012994)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/13d1d4cb241c4d368d414514e1fbc9db~tplv-k3u1fbpfcp-zoom-1.image)]

这里的getNextGenerator方法需要看一下 ** 这里是及其重要的分支逻辑**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2v8H2zD-1658542012994)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eaff92b8ac1648188db67a562fc2bf4e~tplv-k3u1fbpfcp-zoom-1.image)]

getNextState方法也需要看一下,这里是及其重要的分支逻辑

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haiBNKN0-1658542012994)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2719a489e82445cf82411df2a90e8947~tplv-k3u1fbpfcp-zoom-1.image)]

  1. DecodeJob.runGenerators

顺便说一句,11中的几个方法配合这里的runGenerators不就是和okhttp一样的责任链模式吗,又是天下大同。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTTVhWg6-1658542012995)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d9a5d0dd349840c281a0a156bf5f629e~tplv-k3u1fbpfcp-zoom-1.image)]

  1. DecodeJob.reschedule

如果方法走到这里说明需要去网络去请求数据,请求完成后Glide会把数据存储到磁盘中,这个过程很耗时Glide的做法是不继续等待数据返回。而是调用reschedule,reschedule会重新把DecodeJob添加到线程池中进行调度,这样如果请求成功将数据存放到磁盘的话,那么我们下一次线程池再调度到我们的DecodeJob的时候就会成功从磁盘缓存中获取到数据同步返回。(个人感觉这里的逻辑是Glide里面最精妙的了,我看懂的时候拍着大腿直呼过瘾)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bmNnCXzR-1658542012995)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a0c42fe755b944cca1d0e99aaf2c5f9d~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DytxodrF-1658542012995)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ddaa7d9da95a4b77ae07d5de81d9a421~tplv-k3u1fbpfcp-zoom-1.image)]

  1. DecodeJob.decodeFromRetrievedData方法从磁盘中获取图片数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVpDK1Oc-1658542012996)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e5a23bacf51c485aae7efc9c3e7b4da8~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 主流程结束

分支流程

Glide如何加载内存资源

Enging.loadFromMemory
内存缓存的源码要从Engine.load方法开始

  1. Engine.load

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N158z50P-1658542012996)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6252ab5bb47e44878ea9bdb26f3a5721~tplv-k3u1fbpfcp-zoom-1.image)]
下图说明EngineKey如何唯一的标识某一个图片资源key的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMuPz0oW-1658542012997)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/05856f5f15fc4ad18951a1cf10688a41~tplv-k3u1fbpfcp-zoom-1.image “EngineKey如何唯一的标识某一个图片资源key”)]

  1. Engine.loadFromMemory方法加载内存缓存数据

后面我们会分别查看loadFromActiveResources和loadFromCache方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4xHtxOsY-1658542012997)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/925a90a219f3426e9475a68d570205b6~tplv-k3u1fbpfcp-zoom-1.image)]

  1. loadFromActiveResources和loadFromCache两个方法分析
  • loadFromActiveResources从正在请求的资源中查找图片资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbtYTu1o-1658542012998)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/18ca9fd362e94fa3bfd9c051f0dd9181~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SncqAdXK-1658542012998)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/60a58dfe664944abafaada9e6336c8f5~tplv-k3u1fbpfcp-zoom-1.image)]

  • loadFromCache方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MwhLCRZ6-1658542012999)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4326d5309a824de98376c13b28477e91~tplv-k3u1fbpfcp-zoom-1.image)]
重点看getEngineResourceFromCache方法

到了Glide,对LruCache上层又做了一次继承,所以最终真实类型是LruResourceCache

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SxX6bvEP-1658542012999)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/565c462e25944bbe83c293c8fdd8ab55~tplv-k3u1fbpfcp-zoom-1.image)]

Glide是如何去磁盘中加载缓存的

看ResourceCacheGenerator、DataCacheGenerator这两个类,磁盘缓存加载策略是在DecodeJob.getNextGenerator方法中进行的。

ResourceCacheGenerator
  1. ResourceCacheGenerator

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JoSvFl1s-1658542013000)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1e1ef43a6294949805a9a9bfe7a2c6e~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ojsuv1SC-1658542013000)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a19d2da628ae432480b244c6b2606fbb~tplv-k3u1fbpfcp-zoom-1.image)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ReyVVbJ-1658542013000)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dced1e16b8b14e4687f291dce0e7e7d0~tplv-k3u1fbpfcp-zoom-1.image)]

  1. ResourceCacheGenerator.onDataReady

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ieB0CT9v-1658542013001)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/544020b27f11498f941b9560c741c7b4~tplv-k3u1fbpfcp-zoom-1.image)]

  1. 查看DecodeJob.onDataFetcherReady

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xyDMBvT5-1658542013001)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/65d73399a45141109b53c4ae1af12623~tplv-k3u1fbpfcp-zoom-1.image)]

DataCacheGenerator

DataCacheGenerator用于获取原始的图片数据,处理逻辑和ResourceCacheGenerator相似

Glide如何对原始数据进行转换存储

DataCacheGenerator类中处理

Glide是如何去调用网络获取数据的

暂时猜测是从DataUrlLoader类中获取的

Glide中的线程池是怎么调度的

总结

Glide可以实现生命周期绑定的操作,如果我们的请求是在activity或fragment中请求图片的,则会使用添加fragemtn的方式让我们的请求绑定成功生命周期(理解不了的是,为什么到了现在glide仍然没有向Lifecycle转换的想法)。最终会生成一个RequestManager用来处理请求。
绑定生命周期结束后,则对url进行保存,同时可以决定我们加载的图片类型,例如:Bitmap、Drawable、File。
最后是请求的加载逻辑,首先glide会尝试去内存中获取图片数据,如果获取成功那么直接返回。如果没有获取到内存图片数据,那么会使用线程池进行数据加载。在线程池中执行的加载请求会有一个责任链的逻辑,会依次尝试获取磁盘中的被转换过的图片数据、磁盘中的原始原始图片数、去网络获取数据。需要说明的是如果去网络获取数据是不会马上返回结果的,而是直接返回null,但是他会重复多次将我们的请求加入到线程池等待执行,直到请求成功后存储到磁盘,然后从磁盘中返回glide图片数据。

图片加载框架做了什么

  1. 线程切换
  2. 内存缓存和磁盘缓存处理
  3. 防oom的处理
  4. 列表加载图片图片错乱的问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值