Android 图片加载框架Glide源码详解

我们看Glide的源码从Glide类入手,使用的时候我们先调用的with方法,源码中with有3个多载的方法:下图翻译过来就是activity用FragmentActivity Applicationcontext用 with(Context)还有一个with(View)的

殊途同归,最后都是调用了getRetriever(context).get(context),我们看看最后的get(context)方法 ,如下图, 这就大致分成两类一种是ApplicationContext, 一种是activity,fragment ,两种lifecycle生命周期,下图是证明:

为什么要区分Applicationlifecycler和Activitylifecycler 呢?

在Glide中,区分Application Lifecycle和Activity Lifecycle主要是为了更好地管理图像加载和缓存的策略。

Application Lifecycle:在Android应用程序中,Application Lifecycle指的是从应用程序启动到关闭的整个生命周期。在这个生命周期中,Glide可以根据应用程序的整体状态来调整其行为。例如,当应用程序处于后台时,Glide可以减少图像加载的频率或暂停加载,以节省资源和电量。而在应用程序重新进入前台时,Glide可以恢复正常的加载行为。

Activity Lifecycle:Activity Lifecycle指的是一个Activity从启动到销毁的周期。在这个生命周期中,Glide可以与Activity的各个生命周期回调方法进行交互,以便在适当的时机加载和显示图像。例如,当Activity在用户面前时(onResume()调用后),Glide可以在该时机加载并显示图像。而在Activity被用户离开时(onPause()调用后),Glide可以暂停加载或释放一些资源。

通过区分这两个生命周期,Glide可以更精细地控制图像加载和缓存的行为,以适应不同场景和应用程序需求。这有助于提高应用程序的性能、节省资源并提高用户体验。

同时glide的初始化也是在这里getRetriever方法中完成的

从图上我们也可以看出来with 方法返回的是RequestManager, 里面有一个TargetTracker 跟踪view target的 ,每当RequestManage生命周期变化时,通知各个view。

现在是不是能想到,之前聊的lifecycler两种生命周期和它对上了,Application和activity等他们的生命周期会调用manager的,manager再通知各个view,贯通了整个框架。给你们看一下添加的listener

RequestManager集合了glide的要用的各种类,对Request进行管理,其中里面的load方法返回的是RequestBuilder,这里的load实际上还是调用RequestBuilder里面的load

load的方法还是挺空的,重点是赋值这个model 图片地址。

从下图可以看出,RequestBuilder这个类才是Builder设计模式的主类,我们使用中最后的into方法返回的是Target,大部分逻辑都在这个方法里面了, buildRequest就是重点,

然后走的是obtainRequest

SingleRequest.obtain

SingleRequest获得后,在begin方法中

有个onSizeReady

主角登场,engine.load方法。

里面有glide加载缓存的逻辑

下图可以看到是先加载内存中的处理过的resource,里面是一个hashmap维护的key resource 键值对的缓存,第二个就是采取了lru算法的采用linkedhashmap的内存数据

然后是调用了waitForExistingOrStartNewJob方法,开始decodeJob 解码工作

runWrapped()方法, runGenerators方法, currentGenerator.startNext()

值得看的是currentGenerate是下图中3个的哪一个呢,从逻辑上看3个会依次遍历,分别是先处理过的resource缓存,然后是data缓存,最后是Source网络加载, 这也是glide的三级缓存。我们只讲一个SourceGenerator,里面也有下载图片的modelloader,其他两个的逻辑差不多,不再赘述了。下面就要开始讲根据model,data找modelloader的逻辑了,做好心理准备,不简单,网上大都是一笔带过(因为他们也弄不清,的确有点复杂,绕来绕去),好不容易全网找到一篇,不知道是他的版本旧的,还是他理解的不对,珍惜吧,我认为是全篇最难的地方了。

3个也都会调用loadData.fetcher.loadData,重点是找到这个loadData


handles 过滤筛选出可以处理我们数据类型model的modelloader ,比如我们图片用的是https的String

String的有3个,但如果你是http开头的网络url的话就只有StringLoader.Streamfactory了,可以看他们3个各种的handles

还没完,用Uri InputStream 来代替执行

有5个,而符合我们http或https的就只有append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())了

又转为GlideUrl.class, InputStream.class,我们再去工厂里面找,经过三次我们才真正找到 HttpGlideUrlLoader.Factory()

想起前面sourceGenerate 的 loaddata.fetcher.loaddata没有,就是这个HttpUrlFetcher

下载图片的找到了,拿到数据之后的data的回调就是listener来做了,比较简单就不说了,至此难点讲完了。

然后我们跳回SingleRequest类中

然后你会发现这个begin是由 RequestManager.into方法中的requestManager.track(target, request);发起的

随后我们看一下as相关的方法,有三个,其实是两个GifDrawable和drawable是一类,还有一类是bitmap,那么glide为什么将drawable和bitmap 分开呢

看下图,因为glide把两种分成了两个类target view,view的setImageBitmap 和setImageDrawable两个不同的方法加载Resource。

再有就是RequestBuilder关于apply函数加载options

RequestOptions options = new RequestOptions()

复制代码
            .placeholder(R.mipmap.loading)                //加载成功之前占位图

            .error(R.mipmap.loading)                    //加载错误之后的错误图

            .override(400,400)                                //指定图片的尺寸

            //指定图片的缩放类型为fitCenter (等比例缩放图片,宽或者是高等于ImageView的宽或者是高。)

            .fitCenter()

            //指定图片的缩放类型为centerCrop (等比例缩放图片,直到图片的狂高都大于等于ImageView的宽度,然后截取中间的显示。)

            .centerCrop()

            .circleCrop()//指定图片的缩放类型为centerCrop (圆形)

            .skipMemoryCache(true)                            //跳过内存缓存

            .diskCacheStrategy(DiskCacheStrategy.ALL)        //缓存所有版本的图像

            .diskCacheStrategy(DiskCacheStrategy.NONE)        //跳过磁盘缓存

            .diskCacheStrategy(DiskCacheStrategy.DATA)        //只缓存原来分辨率的图片

            .diskCacheStrategy(DiskCacheStrategy.RESOURCE)    //只缓存最终的图片

             .dontTransform()  //禁用图形变换功能,这个方法时全局的,导致其他地方的图片也不可进行图形变换了,慎用.

            .dontAnimate();//跳过动画

Glide还实现了ComponentCallbacks2接口,这个是内存监测的,我们的Activity等也都会用它

在内存不足的时候,对自己占用的进行清理。

最后用图来总结吧,没有捋顺的童鞋可以参考看看,有其他疑问的,咱评论区见了。

相关推荐
蒙奇·D·路飞-11 分钟前
Kotlin安卓app版本自动升级设计实现
android
博客zhu虎康18 分钟前
小程序按钮实现先表单校验再走手机号获取功能
android·javascript·小程序
码途漫谈20 分钟前
Easy-Vibe高级开发篇阅读笔记(十三)——多平台开发之Android App 原生开发
android·人工智能·笔记·ai·开源·ai编程
街灯L22 分钟前
【ADB】使用ADB工具箱卸载安卓系统软件
android·adb
赏金术士30 分钟前
Kotlin 从入门到进阶 之泛型 模块(七)
android·开发语言·kotlin
恋猫de小郭1 小时前
经典,Flutter iOS 又修复了一个构建问题,还是很抽象
android·前端·flutter
Kapaseker1 小时前
不吹牛逼!精通 Compose 绘制(一)
android·kotlin
黄林晴1 小时前
Android 终于做桌面了,而三星 DeX 早已把路趟完
android
Digitally1 小时前
如何连接安卓手机到 Mac?2026 年 7 种可靠方法
android·macos·智能手机
克里斯蒂亚诺更新1 小时前
Android Studio的运行一个简单的apk和模拟器
android·ide·android studio