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等也都会用它

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

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


相关文章:
Android 图片加载框架Glide源码详解
我们看Glide的源码从Glide类入手,使用的时候我们先调用的with方法,源码中with有3个多载的方法:下图翻译过来就是activity用FragmentActivity Applicationcontext用 with(Context)还有一个with(View)的 殊途…...
知识竞赛活动舞台搭建需要多少钱
知识竞赛活动舞台搭建的费用会根据不同的竞赛活动规模和要求而有所不同。对于小型的知识竞赛活动,如学校内部组织的知识竞赛或社区的知识竞赛活动,舞台搭建的费用往往相对较低。在这种情况下,可能只需要一些简单的装饰和道具,例如…...
07set注入级联属性和特殊字符及表达式语言
级联属性赋值(了解) 概述 级联属性赋值就是给某个对象属性的属性赋值,就是给对象关联的对象的属性赋值 Clazz班级类 public class Clazz {private String name;public Clazz() {}public Clazz(String name) {this.name name;}//set和get方法以及toString方法 }Student有cl…...
用AI在小红书做早教启蒙,2个月涨粉11.7万,获赞10万的新流量玩法
本期是赤辰第29期AI项目教程,底部准备了9月粉丝福利,可以免费领取。母婴、教育一直以来是最不缺流量的两大“真香”赛道。那么AI时代下有怎样新流量红利和玩法?接下来就给大家拆解一个在小红书上做AI绘画启蒙早教资源变现的新玩法!…...
Recommender Systems in the Era of Large Language Models (LLMs)
本文是LLM系列文章,针对《Recommender Systems in the Era of Large Language Models (LLMs)》的翻译。 大语言模型时代的推荐系统 摘要1 引言2 相关工作3 基于LLM推荐系统的深度表示学习4 预训练和微调LLM用于推荐系统5 提示LLM用于推荐系统6 未来方向6.1 幻觉缓解…...
红心向阳 百鸟朝凤
背景 最近在玩 folium 模块,基于使用过程中的一些个人体验,对 folium 进行了二次封装,开源在 GpsAndMap.在使用的过程中,发现在地图上打图标是可以进行旋转的。遇到就发现了一些有意思的玩法。 隔海的相望 下面的代码在地图 厦…...
C语言自己实现一个memcpy函数
目录 按字节拷贝实现memcpy按4字节拷贝实现memcpyTips 在 C 语言中,我们可以自己实现 memcpy 函数来实现内存数据的拷贝操作。memcpy 函数用于将指定长度的数据从源地址复制到目标地址。 按字节拷贝实现memcpy #include <stdio.h>void* my_memcpy_byte(void*…...
C#教师考勤管理系统asp.net+sqlserver
3.3.1 员工部分 1:请假管理:包括填写请假条,提交申请,查看审批,审核请假等等。 2:考勤管理:针对具体的员工考勤的统计等管理。 3:个人资料管理:进行个人信息管理…...
Nginx代理配置详解
一、什么是代理 1、正向代理(forward proxy) 正向代理,简单的说就像是一个跳板,它隐藏了真实的请求客户端(IP),服务端不知道真实的客户端是谁,客户端请求的服务都由代理服务器来代替请求。 举个例子来说…...
DAG 的深度优先搜索标记
/**\ | DAG 的深度优先搜索标记 | INIT: edge[][] 邻接矩阵 ; pre[], post[], tag 全置 0; | CALL: dfstag(i, n); pre/post: 开始 / 结束时间 \**/ int edge[V][V], pre[V], post[V], tag; void dfstag( int cur, int n) { // vertex: 0 ~ n-1 pre[cur] tag; for…...
网络存储解决方案:选择与配置
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
java中BigDecimal除法运算指定小数点保留位数和取舍规则
java中使用BigDecimal进行相除运算时,为了避免抛出ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。最好指定小数点保留位数和取舍规则。 取舍规则 ROUND_CEILING: 舍位时向正无穷方向取值。即:向上取…...
车联网远程监控管理提升车辆调度效率,实现高效运营
随着智慧城市建设与物联网技术发展,车辆使用4G工业路由器网络实现车联网,并对车上视频监控、GPS定位以及温湿度传感器等信息进行数据采集和实时传输。这些数据的采集和监测将通过4G网络上传到管理平台,为车辆调度和运行效率的优化提供了有力的…...
数据治理-数据建模和设计
定义 发现、分析和确定数据需求的过程,用一种称为数据模型的精确形式表示和传递这些数据需求。过程是循环迭代的,可能包括概念、逻辑和物理模型。 常见的6种数据模型 关系模式、多维模式、面向对象模式、事实模式、时间序列模式、NoSQL模式。根据描述详…...
博客系统(升级(Spring))(四)(完)基本功能(阅读,修改,添加,删除文章)(附带项目)
博客系统 (三) 博客系统博客主页前端后端个人博客前端后端显示个人文章删除文章 修改文章前端后端提取文章修改文章 显示正文内容前端后端文章阅读量功能 添加文章前端后端 如何使用Redis项目地点: 博客系统 博客系统是干什么的? CSDN就是一…...
常用的辅助类(必会)
1.CountDownLatch package com.kuang.add;import java.util.concurrent.CountDownLatch;//计数器 减法 public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {//总数是6,必须要执行任务的时候,再使用…...
Java常用类之 String、StringBuffer、StringBuilder
Java常用类 文章目录 一、字符串相关的类1.1、String的 不可变性1.2、String不同实例化方式的对比1.3、String不同拼接操作的对比1.4、String的常用方法1.5、String类与其他结构之间的转换1.5.1、String 与基本数据类型、包装类之间的转换1.5.2、String 与char[]的转换1.5.3、…...
linux在所有文件中查找某一个字符串
linux在所有文件中查找某一个字符串 有时候我们需要在大量文件中查找某一个字符串,手工一个一个打开文件查找非常耗时,我们可以使用 find 和 xargs 两个命令来实现查找指定字符串。 命令详解 find <directory> -type f -name "*.c" |…...
WebSocket vs SSE: 实时数据推送到前端的选择与实现(详细)
Websocket和Server-Sent Events 对比推送数据给前端及各自的实现 二者对比WebSocket:Server-Sent Events (SSE):选择 WebSocket 还是 SSE: Websocket 实现使用原生 WebSocket API:使用 Netty 创建 WebSocket:总结和选择…...
Redis从入门到精通(二:数据类型)
数据存储类型介绍 Redis 数据类型(5种常用) string hash list set sorted_set/zset(应用性较低) redis 数据存储格式 redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储 数据类型指的是存储的数据…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
