不敢说懂你 - Glide硬核源码剖析

问题

Glide加载流程?

Glide整体架构?

Glide数据加载的来源?

Glide缓存加载的流程?

Glide线程切换原理?

Glide如何感知Activity?

Glide哪种情况会返回应用级的RequestManager?

带着一些问题去阅读…

使用示例

本篇主要基于glide:4.12.0进行分析。下面是Glide主要的使用示例。

repositories { google()mavenCentral()
}dependencies { implementation 'com.github.bumptech.glide:glide:4.12.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}
 Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);

可以看到,Glide的加载主要分三步:with()load()into()。理解了这三步Glide做了什么,基本就理解了Glide源码加载图片的大体逻辑和框架了。

with()

Glide的with()方法的目的是根据不同的上下文context获得RequestManager对象。

RequestManager对象解释:A class for managing and starting requests for Glide.

下面开始详细分析。

首先看Glide中with()方法所有的重载函数:

RequestManager with(Context context)
RequestManager with(android.app.Activity)
RequestManager with(androidx.fragment.app.Fragment)
RequestManager with(androidx.fragment.app.FragmentActivity)
RequestManager with(View view)

以Glide中的 with(android.app.Activity)为例:

  public static RequestManager with(@NonNull FragmentActivity activity) {return getRetriever(activity).get(activity);}

可以看到,RequestManagergetRetriever(activity).get(activity)得到,因此有两个问题:

1 getRetriever(activity)获得什么对象?

2 这个对象的get()获得什么?

首先看第一个问题,看getRetriever(activity):

private static RequestManagerRetriever getRetriever(@Nullable Context context) {...return Glide.get(context).getRequestManagerRetriever();}

getRetriever(activity)获得了RequestManagerRetriever对象。

接下来进RequestManagerRetriever对象看它的get()实现,它根据with()重载方法参数的不同进行不同重载:

RequestManager get(Context context)
RequestManager get(android.app.Activity)
RequestManager get(androidx.fragment.app.Fragment)
RequestManager get(androidx.fragment.app.FragmentActivity)
RequestManager get(View view)

以其中一个为例:

  public RequestManager get(@NonNull FragmentActivity activity) {if (Util.isOnBackgroundThread()) {return get(activity.getApplicationContext());} else {assertNotDestroyed(activity);frameWaiter.registerSelf(activity);FragmentManager fm = activity.getSupportFragmentManager();return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));}}

可以看到,RequestManager返回两种类型,分别是当是子线程时的get(activity.getApplicationContext());和其他的supportFragmentGet()

首先看with()在子线程中统一返回的应用级别RequestManager单例,看 get(activity.getApplicationContext());

 @NonNullpublic RequestManager get(@NonNull Context context) {...if (context instanceof FragmentActivity) {return get((FragmentActivity) context);...}

继续追这个get()方法的具体实现:

  public RequestManager get(@NonNull Context context) {if (context == null) {throw new IllegalArgumentException("You cannot start a load on a null Context");} else if (Util.isOnMainThread() && !(context instanceof Application)) {if (context instanceof FragmentActivity) {return get((FragmentActivity) context);} else if (context instanceof Activity) {return get((Activity) context);} else if (context instanceof ContextWrapper&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {return get(((ContextWrapper) context).getBaseContext());}}return getApplicationManager(context);}

看到这一行:if (Util.isOnMainThread() && !(context instanceof Application)),这行判断不仅决定了子线程中直接返回getApplicationManager(context)方法,而且当这个传入的context是Application时,也返回全局的getApplicationManager(context)方法获得的应用级别RequestManager

继续追这个getApplicationManager(context)方法的具体实现:

 @NonNullprivate RequestManager getApplicationManager(@NonNull Context context) {if (applicationManager == null) {synchronized (this) {if (applicationManager == null) {Glide glide = Glide.get(context.getApplicationContext());applicationManager =factory.build(...);}}}return applicationManager;}

至此我们知道了with()返回是应用级别RequestManager单例:applicationManager的两种情况:子线程+context=Application

那么不是子线程时的supportFragmentGet()呢,这种情况又是如何生成的RequestManager?我们具体看下RequestManagerRetriever.supportFragmentGet()

 private RequestManager supportFragmentGet(@NonNull Context context,@NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {//获取空fragment,无则创建SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);// 让fragment持有RequestManagerRequestManager requestManager = current.getRequestManager();if (requestManager == null) {//如果空fragment没有RequestManager,就创建一个Glide glide = Glide.get(context);requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);...//让空fragment持有RequestManagercurrent.setRequestManager(requestManager);}//返回页面级别的RequestManagerreturn requestManager;}

继续看这个新fragment怎么创建的:

private SupportRequestManagerFragment getSupportRequestManagerFragment(@NonNull final FragmentManager fm, @Nullable Fragment parentHint) {//通过tag找到Activity中的空fragmentSupportRequestManagerFragment current =(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);if (current == null) {//findFragmentByTag没找到空fragment,有可能是延迟问题?再从Map中找一下current = pendingSupportRequestManagerFragments.get(fm);if (current == null) {//确实没有空fragment,就创建一个current = new SupportRequestManagerFragment();current.setParentFragmentHint(parentHint);//缓存进MappendingSupportRequestManagerFragments.put(fm, current);//空fragment添加到Activity,使其能感知Activity的生命周期fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/826300.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyQt6实战7--文本编辑器

一个简单的文本编辑器 features: 1.open 一个文件夹作为项目 2.save 保存当前窗口的内容 3.退出 4.双击文件可以打开文件内容 5.简单的python高亮 6.双击相同文件,会找到之前打开过的文件 打开一个文件夹 打开项目,双击打开文件 保存 代码&#xf…

CSRF漏洞

文章目录 目录 文章目录 一.什么是CSRF 二.CSRF漏洞工作原理 一.什么是CSRF CSRF(Cross-Site Request Forgery)漏洞,也被称为跨站请求伪造漏洞,是一种Web应用程序安全漏洞。当受害者在已经登录了某个网站的情况下,访问…

吴恩达机器学习笔记 三十五 异常检测与监督学习

什么时候选择异常检测? 正样本 ( y 1 ) 的数量非常少 负样本 ( y 0 ) 的数量非常多 有很多不同的异常,现有的算法不能从正样本中得知什么是异常,或未来可能出现完全没见过的异常情况。 例如金融欺诈,隔几个月或几年就有新的…

java+idea+mysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码

javaideamysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码 随着人工智能技术的快速发展,语音识别与自然语言理解技术的成熟应用,基于人工智能的智能导诊导医逐渐出现在患者的生活视角中,智能导诊系统应用到医院就医场景中&#xff0c…

jvm-接口调用排查

问题描述 线上碰到个问题,某个接口调用时间特别长,线上调用接口直接报gateway time out 分析处理 1、先关闭该功能 (该功能是非核心功能) 2、本地起服务连环境排查,发现本地正常。并且线上其他接口正常,…

顺序表复习(C语言版)

数据结构是什么? 数据结构就是为了把数据管理起来,方便我们的增删查改 数据结构是计算机存储、组织数据的方式 数组就是一种最基础的数据结构 顺序表是什么? 顺序表就是数组 Int arr[100] {1,2,3,4,5,x,……} 修改某个数据&#xff1a…

Mac下删除旧版本.net sdk

参照微软官网给的方法,Releases dotnet/cli-lab (github.com) 好像不能直接的解决问题,我做一下补充,希望对需要删除旧版本sdk的小伙伴们有所帮助 1:下载工具包 Releases dotnet/cli-lab (github.com) 2:打开终端,cd切换到该文件的制定目录 3:然后按照提示一步步执行…

java核心类

一,String字符串 1.1,String字符串是引用类型,且不可变 String str1 "Hello";String str2 str1.concat(" World"); // 使用concat方法连接字符串,返回一个新的字符串对象System.out.println(str1); // 输出:Hello,原始…

C语言:复习

文章目录 思维导图数组和指针库函数的模拟实现判断大小端 最近知识学的差不多了,因此开始复习,本篇开始的是对于C语言的复习 思维导图 下面就依据下图,进行内容的整理 数组和指针 这个模块算是C语言中比较大的一个模块了,具体概…

流媒体协议--RTMP

文章目录 RTMP播放基本流程TCP握手过程RTMP握手过程connect连接createStream 创建流play 播放命令deleteStream删除流RTMP数据组成 RTMP(Real Time Messaging Protocol)是一个应用层协议,主要用于在Flash player和服务器之间传输视频、音频、控制命令等内容。 该协议…

【笔试强训_Day06】

文章目录 1.字符串相乘 1.字符串相乘 题目链接 解题思路: 高精度乘法,注意要学会下面这种列式相乘的形式🍎 注意细节❗: ① 🍎 首先把列式相乘的数据都存放到数组中去, 然后再对数组中的数据进行取余进…

C++:运算符重载和“const”成员

hello,各位小伙伴,本篇文章跟大家一起学习《C:运算符重载》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 ! 文章目录 赋值运算符重载1. 运算符重载2.赋值运算符重载第一个点第二个点&…

迅雷下载不了的资源怎么下载?

我想下载Boost库,但是下载不下来 用迅雷下载是一直卡在0k 后来尝试在centos上用wget进行下载,竟然可以 wget https://boostorg.jfrog.io/artifactory/main/release/1.85.0/source/boost_1_85_0.tar.gz

揭开ChatGPT面纱(一):准备工作(搭建开发环境运行OpenAI Demo)

文章目录 序言:探索人工智能的新篇章一、搭建开发环境二、编写并运行demo1.代码2.解析3.执行结果 本博客的gitlab仓库:地址,本博客对应01文件夹。 序言:探索人工智能的新篇章 随着人工智能技术的飞速发展,ChatGPT作为…

2024燃动智火-业务视角的中国企业AI+学习发展报告

来源:新华三 学习型组织的数字化转型是众多企业关注的焦点,数字战略需要人才升级,数字 化学习加速人才培养。AI 技术在学习中的运用,为企业学习型组织的数字化转型插 上了飞翔的翅膀。这份报告解码了AI 时代企业的学习发展&#…

混合现实(MR)开发框架

混合现实(MR)开发框架为开发者提供了构建MR应用程序所需的基本工具和功能。它们通常包括3D引擎、场景图、输入系统、音频系统、网络功能以及支持同时处理现实世界和虚拟世界信息的功能。北京木奇移动技术有限公司,专业的软件外包开发公司&…

springboot+ssm基于Java的小型企业银行账目管理系统代码Lw

本毕业设计课题要求学生基于软件工程方法,根据课题的需求,给出小型企业银行账目管理系统概要设计、详细设计、数据库的设计以及系统实现和测试,并撰写规范的毕业设计说明书。该系统的主要模块有:系统管理、帐目管理、查询统计、用…

如何使用 ArcGIS Pro 制作边界晕渲效果

在某些出版的地图中,边界有类似于“发光”的晕渲效果,这里为大家介绍一下如何使用ArcGIS Pro 制作这种晕渲效果,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的行政区划数据,除了行政区划数据&#xff0c…

【Flutter】多语言方案二:GetX 版

介绍 多语言方案:GetX版,需要手动自定义字符串引用常量,优点不需要自己管理状态。 目录 介绍运行效果一、安装 GetX二、使用1.语言配置 在lib/core下创建一个language文件夹,文件夹下创建一个local.dart文件2.language文件夹下创…

程序员自由创业周记#32:新产品构思

程序员自由创业周记#32:新产品构思 新作品 我时常把自己看做一位木匠,有点手艺,能做一些作品养活自己。而 加一、Island Widgets、Nap 就是我的作品。 接下来在持续维护迭代的同时,要开启下一个作品的创造了。 其实早在2022的1…