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

news2024/11/16 21:42:38

问题

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());

 @NonNull
  public 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)方法的具体实现:

 @NonNull
  private 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持有RequestManager
   RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
   
      //如果空fragment没有RequestManager,就创建一个
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      ...
      //让空fragment持有RequestManager
      current.setRequestManager(requestManager);
    }
   
   //返回页面级别的RequestManager
    return requestManager;
  }

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

private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
   
   //通过tag找到Activity中的空fragment
  SupportRequestManagerFragment 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);
      //缓存进Map
      pendingSupportRequestManagerFragments.put(fm, current);
      //空fragment添加到Activity,使其能感知Activity的生命周期
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  

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

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

相关文章

[论文阅读链接]

CVPR2023:Learning Human-to-Robot Handovers from Point Clouds http://t.csdnimg.cn/OfSnShttp://t.csdnimg.cn/OfSnS仿真工具:dm_control: Software and Tasks for Continuous Control dm_control 翻译: Software and Tasks for Continuous Control…

python免费调用阿里云通义千问(q-wen-max)大模型API

文章目录 通义千问开通免费API Keypython调用阿里云通义千问API 通义千问 通义千问,是基于阿里巴巴达摩院在自然语言处理领域的研究和积累。采用更先进的算法和更优化的模型结构,能够更准确地理解和生成自然语言、代码、表格等文本。 支持更多定制化需…

js 特定索引下拆分字符串并组建成新的字符串数据

要在特定索引处拆分字符串,请使用 slice 方法获取字符串的两个部分,例如 str.slice(0, index) 返回字符串的一部分,但不包括提供的索引,而 str.slice(index) 返回字符串的其余部分。 过程:我们创建一个可重用的变量&a…

Linux-用户管理类命令实训

查看根目录下有哪些内容 进入/tmp目录,以自己的学号建一个目录,并进入该目录 像是目前所在的目录 在当前目录下,建立权限为741的目录test1 在目录test1下建立目录test2/test3/test4 进入test2,删除目录test3/test4 (7&…

paddle.net怎么付款?paddle.net怎么订阅?

有需要的小伙伴可以使用Fomepay的卡进行订阅支付,我这里使用的是491090卡段,开卡步骤很简单,点击获取卡片 1、注册 2、填写姓名使用拼音或者英文名都可以 3、支付宝或者微信支付

JavaWeb-登录校验

会话技术 浏览器使用的是http协议,多次请求间数据是不能共享的,例如我们要去访问用户数据的接口,但这时候用户是否已经登入了呢?是不知道的,为了解决这个问题,于是引入了会话跟踪技术。 会话:…

一次Ambari安装记录

引言 Ambari是一个开源的Apache项目,它提供了一个直观易用的Web界面,用于管理、监控和配置Apache Hadoop集群。它是一个集群管理工具,可以帮助管理员轻松地部署、管理和监控Hadoop集群的各种组件,如HDFS、YARN、MapReduce、Hive、HBase等。通过Ambari,用户可以在集群中添…

【GPTs分享】GPTs分享之Image Recreate | img2img​

简介 该GPT是一个专门用于图像编辑、重建和合并的工具。它通过详细的自动图像描述和生成,帮助用户从源图像中重现或修改图像。此工具设计用于为视障用户提供图像内容的详细描述,并生成全新的图像,以满足特定的视觉需求。 主要功能 \1. 图像…

存储人视角:人工智能AI + 大模型

原文来自于知乎存储专栏: 存储人视角:人工智能AI 大模型 前沿 我的角色 背景 AI 出场 效果 一个宠娃狂魔 娃喜爱并有奥特曼玩具 她的奥特曼玩具会跳舞了 娃对我的崇拜和爱又多了一分......amazing 杭州网商路艾弗森 球队需要制作LOGO 形象生动…

【学习】对于加密接口、签名接口如何进行性能测试

随着科技的飞速发展,加密接口和签名接口在我们的日常生活中扮演着越来越重要的角色。从在线支付到信息安全,它们始终默默地守护着我们的数字世界。然而,随着应用场景的不断扩展,性能测试变得尤为重要。今天,让我们一起…

【6】mysql查询性能优化-关联子查询

【README】 0. 先说结论:一般用inner join来改写in和exist,用left join来改写not in,not exist;(本文会比较内连接,包含in子句的子查询,exist的性能 ) 1. 本文总结自高性能mysql 6…

PLC中连接外部现场设备和CPU的桥梁——输入/输出(I/O)模块

输入(Input)模块和输出(Output)模块简称为I/O模块,数字量(Digital,又称为开关量)输入模块和数字量输出模块简称为DI模块和DQ模块,模拟量(Analog)输…

求a+aa+aaa+……(C语言)

一、题目&#xff1b; 二、N-S流程图&#xff1b; 三、运行结果&#xff1b; 四、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int a 0;int n 0;int i 0;int result 0;int tn 0;//提示用户&am…

Linux学习第52天:Linux网络驱动实验(二):一往(网)情深

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本节笔记的目录如下&#xff1a; 四、I.MX6ULL网络驱动简介 1.I.MX6ULL网络外设设备树 2.I.MX6ULL网络驱动源码简析 3.fec_netdev_ops操作集 4.Linux内核PHY子…

删除word中下划线的内容

当试卷的题目直接含答案&#xff0c;不利用我们刷题。这时如果能够把下划线的内容删掉&#xff0c;那么将有利于我们复习。 删除下划线内容的具体做法&#xff1a; ①按ctrl H ②点格式下面的字体 ③选择下划线线型中的_____ ④勾选使用通配符并在查找内容中输入"?&qu…

OSI网络七层协议 ——(随手笔记)

1.OSI OSI&#xff08;Open System Interconnect&#xff09;&#xff0c;即开放式系统互连。 一般都叫OSI参考模型&#xff0c;是ISO组织在1985年研究的网络互连模型。该体系结构标准定义了网络互连的七层框架&#xff08;物理层、数据链路层、网络层、传输层、会话层、表示层…

【论文阅读】Attention is all you need

摘要 主要的序列转换模型是基于复杂的循环或卷积神经网络&#xff0c;其中包括一个编码器和一个解码器。性能最好的模型还通过一种注意力机制将编码器和解码器连接起来。我们提出了一种新的简单的网络架构&#xff0c;Transformer&#xff0c;完全基于注意机制&#xff0c;完全…

数据结构-基于ArrayList的源码模拟

文章目录 继承关系 :1. 构造方法的模拟2. 扩容机制的分析3. 查找方法的模拟4. 获取,修改元素的方法模拟5. 添加元素的模拟6. 删除元素的模拟7. removeAll与retainAll的模拟总结: 边缘方法以及总代码 继承关系 : 1. 构造方法的模拟 源码中我们的ArrayList的构造方法给出了三种实…

【Java基础】19.继承(面向对象的三大特征:封装、继承、多态)

文章目录 前言一、继承的概念二、继承的步骤1.类的继承格式2.继承的实例3.继承类型 三、继承的特性四、继承的关键字1.extends关键字2.implements关键字3.super 与 this 关键字4.final 关键字 五、构造器 前言 一、继承的概念 继承是java面向对象编程技术的一块基石&#xff…

Git - 在PyCharm/Idea中集成使用Git

文章目录 Git - 在PyCharm/Idea中集成使用Git1.新建GitHub仓库2.将仓库与项目绑定3.在PyCharm中使用Git4.新建Gitee仓库5.将仓库与项目绑定6.在IDEA中使用Git Git - 在PyCharm/Idea中集成使用Git 本文详细讲解了如何在 PyCharm 或 Idea 中配置 Gitee 或 GitHub 仓库&#xff0…