从源码的角度带你分析Glide整体加载流程以及设计模式

最新源码Glide4.12框架之加载图片流程源码分析 一、前言 Android图片加载框架,在android应用开发中是一个常见的话题。在12、13年的时候我记得可能用的最多的是XUtils的一套框架(更早之前叫aFinal框架),这个框架中提供imageUtils用于在android应用的开发中完成远程图片的加载。再后来呢,有Picasso、Fresco、Glide。而这几年的开发经验来看,Glide最为流行。不信,可以查看github上项目地址,分别对比对比watch数、fork数、star数,就能确定Glide确实最为流行。 如何对图片框架技术进行选型? 阅读详情

基本调用流程

这一篇文章我们从源码的角度分析Glide实现,首先我们从一句最简单的使用方式来探索他的设计与实现,可以看到下面这句话是最基础的使用

Glide.with(this)
        .load(R.raw.large_giphy_logo)
        .into(giphyLogoView);

接下来我们一步一步的跟踪他的调用过程,首先我们看到他调用了Glide的with方法并传入了自己的引用,我们可以看到这方法的实现如下:

public static RequestManager with(Activity activity) {
  RequestManagerRetriever retriever = RequestManagerRetriever.get();
  return retriever.get(activity);
}

他调用了RequestManagerRetriever的方法获取了一个RequestManagerRetriever然后在调用get方法获取了一个RequestManager,到这里我们大概基本明白了with方法做的是将当前引用(Activity,Fragment)传递进去并获取一个和当前引用绑定的RequestManager,到这里大家应该能明白了为什么说Glide绑定了界面的生命周期了吧

接着调用了RequestManager的load方法,可以看到这一步创建了RequestBuilder

public RequestBuilder<Drawable> load(@Nullable Object model) {
  return asDrawable().load(model);
}

最后调用到了loadGeneric方法

public RequestBuilder<TranscodeType> load(@Nullable Object model) {
  return loadGeneric(model);
}

不过从这个方法我们可以看到他只是将传递进来的资源保存了,现在还没有发送真正的网络请求

private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
  this.model = model;
  isModelSet = true;
  return this;
}

然后调用了RequestBuilder的into方法

public Target<TranscodeType> into(ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    if (!requestOptions.isTransformationSet()
            && requestOptions.isTransformationAllowed()
            && view.getScaleType() != null) {
        if (requestOptions.isLocked()) {
            requestOptions = requestOptions.clone();
        }
        switch (view.getScaleType()) {
            case CENTER_CROP:
                requestOptions.optionalCenterCrop(context);
                break;
            case CENTER_INSIDE:
                requestOptions.optionalCenterInside(context);
                break;
            case FIT_CENTER:
            case FIT_START:
            case FIT_END:
                requestOptions.optionalFitCenter(context);
                break;
            //$CASES-OMITTED$
            default:
                // Do nothing.
        }
    }

    return into(context.buildImageViewTarget(view, transcodeClass));
}

在这个方法里面,主要判断了是否设置了Transformation如果设置了,然后根据相应的规则变换bitmap,最后调用了这个into方法

public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
        throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    Request previous = target.getRequest();

    if (previous != null) {
        requestManager.clear(target);
    }

    requestOptions.lock();
    Request request = buildRequest(target);
    target.setRequest(request);
    requestManager.track(target, request);

    return target;
}

在这方法中创建了Request,然后调用requestManager的track方法去执行这个request

void track(Target<?> target, Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

我们再来查看下buildRequest方法

  private Request buildRequest(Target<TranscodeType> target) {
    return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
            requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
}

private Request buildRequestRecursive(Target<TranscodeType> target,
                                      @Nullable ThumbnailRequestCoordinator parentCoordinator,
                                      TransitionOptions<?, ? super TranscodeType> transitionOptions,
                                      Priority priority, int overrideWidth, int overrideHeight) {
    if (thumbnailBuilder != null) {
        // Recursive case: contains a potentially recursive thumbnail request builder.
        if (isThumbnailBuilt) {
            throw new IllegalStateException("You cannot use a request as both the main request and a "
                    + "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
        }

        TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
                thumbnailBuilder.transitionOptions;
        if (DEFAULT_ANIMATION_OPTIONS.equals(thumbTransitionOptions)) {
            thumbTransitionOptions = transitionOptions;
        }

        Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
                ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);

        int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
        int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
        if (Util.isValidDimensions(overrideWidth, overrideHeight)
                && !thumbnailBuilder.requestOptions.isValidOverride()) {
            thumbOverrideWidth = requestOptions.getOverrideWidth();
            thumbOverrideHeight = requestOptions.getOverrideHeight();
        }

        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
        Request fullRequest = obtainRequest(target, requestOptions, coordinator,
                transitionOptions, priority, overrideWidth, overrideHeight);
        isThumbnailBuilt = true;
        // Recursively generate thumbnail requests.
        Request thumbRequest = thumbnailBuilder.buildRequestRecursive(target, coordinator,
                thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight);
        isThumbnailBuilt = false;
        coordinator.setRequests(fullRequest, thumbRequest);
        return coordinator;
    } else if (thumbSizeMultiplier != null) {
        // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
        ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
        Request fullRequest = obtainRequest(target, requestOptions, coordinator, transitionOptions,
                priority, overrideWidth, overrideHeight);
        BaseRequestOptions<?> thumbnailOptions = requestOptions.clone()
                .sizeMultiplier(thumbSizeMultiplier);

        Request thumbnailRequest = obtainRequest(target, thumbnailOptions, coordinator,
                transitionOptions, getThumbnailPriority(priority), overrideWidth, overrideHeight);

        coordinator.setRequests(fullRequest, thumbnailRequest);
        return coordinator;
    } else {
        // Base case: no thumbnail.
        return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
                overrideWidth, overrideHeight);
    }
}

可以看到最后调用了buildRequestRecursive来创建一个Request,在这方法里面通过判断是否设置了thumbnail来创建不同类型的Request,如果没有设置就会创建最基本的请求,也就是SingleRequest

private Request obtainRequest(Target<TranscodeType> target,
                              BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator,
                              TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,
                              int overrideWidth, int overrideHeight) {
    requestOptions.lock();

    return SingleRequest.obtain(
            context,
            model,
            transcodeClass,
            requestOptions,
            overrideWidth,
            overrideHeight,
            priority,
            target,
            requestListener,
            requestCoordinator,
            context.getEngine(),
            transitionOptions.getTransitionFactory());
}

到这里大家可以看到Glide的源码可以说是非常复杂的,总感觉有时候用到项目里是不是有点太重了,就加载个图片,你看看搞了这么多代码~~

一些设计技巧

绑定界面的生命周期

在Glide中可以看到所有的请求都是和当前界面绑定的,比如:activity执行onStop时,其相应的请求应该暂停,那他是怎么绑定的呢,简单来讲就是在当前activity中绑定一个fragment,这样我们就能通过这个fragment获取到相应的生命周期,然后回调到你要处理的地方,然后在作出相应的处理,如果代码:

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void bindLifeCycle(LifeCycleActivity activity) {
    FragmentManager fm = activity.getFragmentManager();
    //将一个fragment绑定到当前界面,这样就能获取到了当前界面的生命周期了
    LifeCycleFragment current = new LifeCycleFragment();
    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
}

这样我们就能在LifeCycleFragment中获取到相应的生命周期了

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class LifeCycleFragment extends Fragment {
    private static final String TAG = "LifeCycleFragment";

    @Override
    public void onStart() {
        super.onStart();
        //TODO 这里回调你的生命周期状态
        Log.d(TAG,"onStart");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG,"onStop");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }
}

参考:https://github.com/android-cn/android-open-project-analysis/tree/master/tool-lib/image-cache/glide

Android 面试之Glide做了哪些优化? Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点.本文以Glide做了哪些优化为切入点,介绍与学习GlideGlide做了哪些优化?要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题?1.图片下载是个耗时过程,我们首先需要考虑的就是图片缓存的问题。 阅读详情

相关推荐

更多 LSTM 变种——应用于 CMAPSS 数据集

本文并模型介绍,只是把一些比较火的技术,像双向注意力机制,自注意力机制这样的比较火的内容,简单的和LSTM堆叠,结果发现效果都不如最基础的,这里作者将本人代码及实现结果,进行展示,给各位想更改LSTM的朋友一些。

2301_77491330的博客 1765

Glide 用到的设计模式,你知道多少?_glide 责任链模式哦

通过原型模式,我们可以根据一个现有对象创建出新的对象,并且可以灵活地修改新对象的属性,而不会影响原始对象。这样可以避免重复创建相似的对象,提高性能和代码复用性。克隆细分又分深拷贝和浅拷贝。听君一席话,如听一席话,我们看下Glide怎么做的。Glide 哪里用到了原型模式呢?在构建请求对象的请求参数就用到了,如下。为什么要用clone,对应什么场景?其实就这个问题我也思考良久,让我们自己写图片加载框架估计就直接new 请求参数,然后把请求参数都塞进去,又不是不能用,这样确实是能用并且一点问题都没有。

2401_84164527的博客 694

IBM 3560M3 R5 坏盘更换记录

公司一台老旧 3650M3在日常巡查过程中发现硬盘报错

ddriv的博客 3941

glide源码中包含了那种设计模式_简析Glide源码

什么是GlideAn image loading and caching library for Android focused on smooth scrolling一个使得Android图片列表滑动时更加流畅的图片加载和缓存库。Glide 优点(1) Glide 不仅是支持图片缓存和加载,它支持 Gif、WebP、缩略图、Video(2) 支持优先级处理(3) 与 Activity/Fragm...

weixin_39789690的博客 604

高频功率放大器的设计实现

摘 要 随着无线通信技术的高速发展,市场对射频电路的需求越来越大,同时对射频电路的性能要求也越来越高。高频功率放大器是位于无线发射级末端的重要部件,为了弥补信号在无线传输过程中的衰耗,要求发射机具有较大功率的输出,通信距离越远,要求的输出功率越大。在高频范围内,为了获得足够大的高频输出功率,就要采用高频功率放大器。 本次课程设计的高频功率放大器的技术指标包括输出功率、效率、功率增益、由于高频频功率放大器的输出功率比较大,耗能比较多,所以工作效率就显得比较重要。本课程设计的高频功率放大器电路由两极功率放大器

qq_43543515的博客 3万+

解决屏幕不亮难题:慷智SerDes DE信号极性配置避坑指南

本文深入探讨了基于慷智AIM95x系列SerDes芯片的嵌入式显示系统开发中,因DE信号极性配置不匹配导致屏幕不亮的典型故障。文章详细解析了DE信号的核心作用与极性定义,提供了慷智SerDes芯片中DE极性寄存器的具体配置方法与调试记录,并给出了从隔离问题、对比时序到波形验证的系统性排查流程,帮助工程师快速定位并解决此类隐蔽问题。

weixin_29185493的博客 141

Glide 用到的设计模式,你知道多少?

Glide 作为一个像Android SDK 一样的第三方图片框架,久经各大项目的考验,read the fuck glide source code ,深入其架构思想,设计模式,对于提升我们的编程能力是无可厚非的。

maniuT的博客 465

【UE5】Vosk插件实战:离线语音识别与TTS朗读全流程解析

本文详细解析了如何在UE5中利用Vosk插件实现离线实时语音转文字功能。从环境配置、插件与模型准备,到核心C++组件封装与蓝图系统搭建,提供了完整的实战教程。重点解决了离线语音识别在游戏开发中的延迟、隐私和网络依赖问题,并演示了从语音识别到TTS朗读的完整交互闭环,为开发安全、实时的语音交互应用提供可靠方案。

weixin_29021291的博客 510

Android源码看设计模式(五)--------基于创建者模式的Glide相关分析

创建者模式 概念: 建造者模式(builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 通俗的来说,所谓创建者模式,就是客户端不必知道产品内部的组成的细节,而且具体的创建者之间是独立的,容易扩展。主要应用场景是当产品有很多的组成部件可以设置,但是我们在使用的时候可以只设置其中一部分,此时就可以使用创建者模式,比如AlertDialog的使用 创建...

双鱼千殇的博客 1456

C#上位机通信层封装:西门子S7NetPlus库的优雅使用

支持S7-1200/1500(机架号0,槽号1)、S7-300/400(机架号/槽号需根据实际配置);支持位(Bit)、字节(Byte)、字(Word)、双字(DWord)、浮点数(Float/Double)等数据类型的读写;支持DB块、输入寄存器(I)、输出寄存器(Q)、内存寄存器(M)、定时器(T)、计数器(C)的操作;轻量无依赖,兼容.NET 5+。首先定义核心枚举和常量,统一规范参数类型,避免硬编码。/// 西门子PLC型号(对应不同的机架/槽号默认配置)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1085

知识图谱大模型系列之 12 LLM 知识图谱构建器:从零到 GraphRAG 使用 LLM 知识图谱生成器在 GenAI 应用中提取和使用知识图谱(教程含源码)

为了更深入地了解 LLM 知识图谱构建器,GitHub 存储库提供了大量信息,包括源代码和文档。此外,我们的文档提供了详细的入门指南,而GenAI 生态系统则提供了有关可用更广泛工具和应用程序的进一步见解。

iCloudEnd的博客 2037

glide源码中包含了那种设计模式_从源码的角度带你分析Glide整体加载流程以及设计模式...

基本调用流程这一篇文章我们从源码的角度分析Glide实现,首先我们从一句最简单的使用方式来探索他的设计与实现,可以看到下面这句话是最基础的使用Glide.with(this).load(R.raw.large_giphy_logo).into(giphyLogoView);接下来我们一步一步的跟踪他的调用过程,首先我们看到他调用了Glide的with方法并传入了自己的引用,我们可以看到这方法的实现...

weixin_39808726的博客 202

利用 Python 构建高效爬虫爬取国家标准文献——从基础到进阶

然而,由于许多标准文献需要从特定网站获取,手动下载既耗时又低效,因此构建自动化爬虫成为一种实用且高效的解决方案。本文从技术选型、网站分析、代码实现到反爬优化,全面讲解了如何爬取国家标准文献。国家标准文献(National Standards Literature)是国家对各领域统一规范的文件,涵盖了技术参数、测试方法、生产工艺等内容。因此,通过自动化爬虫技术进行文献爬取和管理,不仅能解放劳动力,还可以提高数据管理效率。在构建爬虫前,我们需要对目标网站进行分析,包括页面结构、请求方式以及可能的反爬机制。

2201_76125261的博客 2104

Glide系列(四) — Glide缓存流程分析

Glide 是一个图片加载库,跟它同类型的库还有 Picasso、Fresco、Universal-Image-Loader 等。基于 Glide 优秀的缓存管理策略和生命周期关联的特点,目前市面上对 Glide 的使用非常广,因此我们有必要深入研究下 Glide 相关的实现原理,便于更好的使用它。

Elson的博客 1982

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Glide源码探究(二)Glide整体设计

本文参考前辈们的文章,结合源码,从以下角度继续探究Glide的源码设计。个人觉得如果先有一个整体的认识,然后再深入探讨是比较舒服的。本文从以下角度继续探究Glide: Glide整体框架 Glide模块间的调用流程 Glide库 目录结构 Glide的类之间的关系 1.Glide整体框架 结合上面的图,我们分两步探究这个库的工作原理, 第一步:当我们使用这个Glide库加载图片时,它内部先初...

小码匠的博客 318

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

bitmap mfc 加载图片_从 Glide 看Android 中加载图片的正确姿势

作者:北辰来源:https://www.yuque.com/beichen-oyd87/sse6hm/uhnhg2在移动平台上,加载显示图片已经是普通的不能再普通的操作了,但是由于移动设备的一大缺陷:内存较PC来说相对小,而图片占用的内存又是大头,要是没有很好的防范措施,OOM 便会在项目中如影随形。所以,在加载图片这一块,诞生了很多强大的图片加载库,从老牌图片加载框架Universal...

weixin_39869593的博客 110

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Glide系列(五) — Request 构建流程分析

Glide 是一个图片加载库,跟它同类型的库还有 Picasso、Fresco、Universal-Image-Loader 等。基于 Glide 优秀的缓存管理策略和生命周期关联的特点,目前市面上对 Glide 的使用非常广,因此我们有必要深入研究下 Glide 相关的实现原理,便于更好的使用它。

Elson的博客 680

Android 面试之Glide做了哪些优化 _glide 对bitmap 做了哪些优化(2)

Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点.本文以Glide做了哪些优化为切入点,介绍与学习GlideGlide做了哪些优化?要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题?1.图片下载是个耗时过程,我们首先需要考虑的就是图片缓存的问题。

2401_84103216的博客 1173

为了性能,Glide 做了哪些优化?

前言 Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。 但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点。 本文以Glide做了哪些优化为切入点,介绍与学习Glide的源码与原理,如果对您有所帮助,欢迎点赞。 Glide做了哪些优化? 要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题? 1.图片下载是个耗时过

HoukHan的博客 1012

你真的懂了Glide图片框架了吗?它来了,它来了,它带着资源走来了...

简言: 之前写过关于Glide的文章,都是一些如何使用的案例,比较注重使用了,没有考虑它的源码是如何实现的,今天为大家讲解一下源码,从源码的角度让你了解Glide这个神奇的图片框架。 1.Gilde 简介 在泰国举行的谷歌发布者论坛上,谷歌为我们介绍了一个叫Gilde的图片加载库,作者是bumptech。 这个库被广泛的运用在goole的开源项目中,包括2014年goole ...

wk_先森的博客 7950

掌握Glide(2) : 从源码看,Glide是如何关联生命周期的

本文将从源码的角度,分析Glide是如何关联生命周期的。 源码版本均指:4.6.1

微不足道的博客 457

Android图片加载框架的理解--Glide的理解

背景 工作中,最常使用的就是Glide,因此一直想了解它的内部机制。 好早之前看了Glide源码,陷进了源码细节无法自拔,笔记也记了一些比如:“Glide的with方法里,先是封装了RequestManager类,然后封装了xxx类………………”,这些没有意义的流程性的东西。 现在站在整体的角度,希望对Glide有一些有用的理解,也功利性的思考:了解它的原理能带给我哪些好处。 图片加载框架 ...

qq_38261312的博客 348

Glide做了哪些优化?

前言 Glide可以说是最常用的图片加载框架了,Glide链式调用使用方便,性能上也可以满足大多数场景的使用,Glide源码与原理也是面试中的常客。 但是Glide的源码内容比较多,想要学习它的源码往往千头万绪,一时抓不住重点。 本文以Glide做了哪些优化为切入点,介绍与学习Glide的源码与原理,如果对您有所帮助,欢迎点赞。 Glide做了哪些优化? 要想要回答这个问题,我们可以先想一想,如果我们自己要实现一个图片加载框架,我们会思考什么问题? 1.图片下载是个耗时过

winskyan的专栏 617

Glide.js 零依赖轮播组件全指南:安装、初始化、模块化与源码原理剖析

Glide.js 是一个基于 ES6 编写、零第三方依赖的轻量级滑块(slider)与轮播(carousel)组件,项目定位是"只负责滑动,不多也不少"。本指南以官方 README 为骨架,结合仓库源码与测试用例,带你完整掌握 Glide.js 的安装流程、最小可运行标记结构、全部核心配置项、`go()` 移动模式、模块化按需加载、实例 API、事件系统以及 SASS 样式定制方案。读完本文,你可

gitblog_00719的博客 420
上一篇: 手把手教你使用Travis CI自动部署你的Hexo博客到Github上
下一篇: 深入理解Java的4种引用类型
爱上学习啊
博客等级 码龄16年 99粉丝 76原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值