当前位置: 首页 > news >正文

Glide的使用及源码分析

前言

依赖

implementation 'com.github.bumptech.glide:glide:4.16.0'

github: GitHub - bumptech/glide: An image loading and caching library for Android focused on smooth scrolling

基本使用

//加载url
Glide.with(this)
.load(url)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.into(imageView)//加载本地drawable资源
Glide.with(this)
.load(R.mipmap.ic_launcher)
.into(imageView)//加载gif,Glide会智能判断
Glide.with(this)
.load(R.drawable.a)
.into(imageView)//asBitmap只加载静态图片,如果图片为gif则加载第一帧
Glide.with(this)
.asBitmap()
.load(R.drawable.a)
.into(imageView)//后备回调符
Glide.with(this)
.load(url)
.fallback(R.mipmap.ic_launcher) //当url为null时显示
.into(imageView)

 RequestOptions

Glide的配置都可以通过RequestOptions配置,用于提取公共属性,复用。

RequestOptions options = new RequestOptions().placeholder(R.drawable.ic_launcher_background).error(R.drawable.ic_launcher_foreground).fallback(R.mipmap.ic_launcher);Glide.with(this).load(URL).apply(options).into(view);

设置图片大小

宽高单位是px

Glide.with(this).load(URL).override(100,100).into(view);

设置缩略图

RequestBuilder<Drawable> requestBuilder= Glide.with(this).asDrawable().sizeMultiplier(0.5f);//显示原图的50%
Glide.with(this).load(URL).thumbnail(requestBuilder).into(view);

先加载缩略图,再加载原图

//先加载缩略图,再加载原图
RequestBuilder<Drawable> requestBuilder1= Glide.with(this).load(URL1);Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.NONE).thumbnail(requestBuilder1).into(view);

缓存设置

Glide默认开启内存缓存和硬盘缓存

禁用缓存策略

Glide.with(this).load(URL).skipMemoryCache(true).into(view);

硬盘缓存策略

  • DiskCacheStrategy.NONE //不开启硬盘缓存
  • DiskCacheStrategy.DATA //只缓存原始图片
  • DiskCacheStrategy.RESOURCE //只缓存转换后的图片
  • DiskCacheStrategy.ALL //同时缓存原始图片和转换后图片
  • DiskCacheStrategy.AUTOMATIC //智能模式,Glide根据图片资源选择模式
  Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.NONE).into(view);

预加载

  Glide.with(this).load(URL).preload();

文件下载

        new Thread(() -> {FutureTarget<File> target =  Glide.with(MainActivity.this).asFile().load(URL).submit();try {File image =  target.get();File file = new File(getCacheDir(),"file.png");image.compareTo(file);} catch (ExecutionException | InterruptedException e) {throw new RuntimeException(e);}}).start();

图片裁剪

Glide.with(this)
.load(url)
//.centerCrop() //居中剪裁
//.fitCenter() // 默认
.circleCrop() //圆形图片
.into(imageView)

过渡动画

 //过渡动画
Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.NONE).transition(withCrossFade(1000)) //默认为300ms.into(view);

可以自定义动画

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"android:duration="2000"android:fromAlpha="0"android:toAlpha="1" />
Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.NONE).transition(GenericTransitionOptions.with(R.anim.anim_alpha)).into(view)


源码分析

with

 RequestManager requestManager = Glide.with(this);

load

RequestBuilder<Drawable> load = requestManager.load(URL);

into

CustomViewTarget<ImageView, Drawable> target = new CustomViewTarget<ImageView, Drawable>(view) {@Overrideprotected void onResourceCleared(@Nullable Drawable placeholder) {Log.e(TAG, "资源清理");}@Overridepublic void onLoadFailed(@Nullable Drawable errorDrawable) {Log.e(TAG, "加载失败");}@Overridepublic void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {Log.e(TAG, "加载成功");}};CustomViewTarget<ImageView, Drawable> into = load.into(target);

1:RequestBuilder.java

->into

->return into( glideContext.buildImageViewTarget(view, transcodeClass), /* targetListener= */ null, requestOptions, Executors.mainThreadExecutor()); //构造一个ImageViewTarget

->Request request = buildRequest(target, targetListener, options, callbackExecutor); //构造一个请求,接口实现SingleRequest

2:RequestManager.java

->requestManager.track(target, request);

3:RequestTracker.java

->requestTracker.runRequest(request);//两个set集合添加request请求

->request.begin();

4:SingleRequest.java

 ->onSizeReady(overrideWidth, overrideHeight);

5:Engine.java

->memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);//三级缓存

->EngineResource<?> active = loadFromActiveResources(key); //一级缓存活动--运行时缓存

->EngineResource<?> cached = loadFromCache(key); //二级缓存Cache--运行时缓存

->waitForExistingOrStartNewJob

->jobs.get(key, onlyRetrieveFromCache)////三级缓存磁盘-非运行时缓存

6:EngineJob.java

如果缓存里都没有,去请求

->engineJob.start(decodeJob);

7:DecodeJob.java

->run()

->runWrapped()

->case INITIALIZE:

stage = getNextStage(Stage.INITIALIZE);

currentGenerator = getNextGenerator();

runGenerators();

->currentGenerator.startNext()

8:SourceGenerator.java

->startNext()

9:DecodeHelper.java

->loadData = helper.getLoadData().get(loadDataListIndex++);

-> glideContext.getRegistry().getModelLoaders(model)  //这里会取注册的Loaders

10:ModelLoader.java

->LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);

11:HttpGlideUrlLoader.java

->buildLoadData

->return new LoadData<>(url, new HttpUrlFetcher(url, timeout));

12:HttpUrlFetcher.java

->loadData

->loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders()); //发起HttpUrlConnect请求

->getStreamForSuccessfulRequest;//获得InputStream

->stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);//会对InputSteam做一系列的优化,压缩,防止过大导致崩溃

……

->InputStream会转成Bitmap

……

最终回调到CustomViewTarget.onResourceReady

也就是

贴上完整的时序图

Glide生命周期

Glide之所以如此灵活,无须对用户的Activity或Fragment进行管理,避免内存泄漏,在于空白的父类SupportRequestManagerFragment,通过jetpack的lifecycle进行管理。

面试总结

1:在子线程使用Glide.with函数,会发生什么?

答:Glide.with在子线程里不会添加生命周期,在主线程才会添加一个FragmentActivity,绑定使用的Activity生命周期

2:项目中大量使用Glide,会造成内存泄漏问题,请问如何避免?

答:通过Glide.with()传入的对象,尽量是包含能自动回收的Activity等包含生命周期的作用域,避免使用Application这种,造成无法回收现象。

3:使用Glide为什么要加入网络权限?

<uses-permission android:name="android.permission.INTERNET" />

答:因为内部会有HttpURLConnection请求,在执行Request事务后,会先从活动缓存取,如果没有,再去内存缓存,再去磁盘缓存,然后通过HttpUrlFetcher发起HttpURLConnection请求,所有需要网络权限

4:Glide源码里面的缓存,为什么要有 活动缓存 还需要 有内存缓存?或者为什么设计三层缓存?

答:简单来说,一级缓存采用LRU算法,最新最少使用的图片,当请求队列有新的图片时候,会淘汰掉最新最少使用的图片,如果这张图片后面还需要页面展示,那么就会有产生效率问题,因此再增加了一层不采用LRU的内存缓存。

相关文章:

Glide的使用及源码分析

前言 依赖 implementation com.github.bumptech.glide:glide:4.16.0 github: GitHub - bumptech/glide: An image loading and caching library for Android focused on smooth scrolling 基本使用 //加载url Glide.with(this) .load(url) .placeholder(R.drawable.placehol…...

外贸爬虫系统

全球智能搜索 全球智能搜索 支持全球所有国家搜索引擎&#xff0c;及社交平台&#xff0c;精准定位优质的外贸客户&#xff0c;免翻墙 全球任意国家地区实时采集 搜索引擎全网邮箱电话采集 社交平台一键查看采集&#xff08;Facebook,Twitter,Linkedin等&#xff09; 职位…...

CentOS 8 安装 Code Igniter 4

在安装好LNMP运行环境基础上&#xff0c;将codeigniter4文件夹移动到/var/nginx/html根目录下&#xff0c;浏览器地址栏输入IP/codeigniter/pulbic 一直提示&#xff1a; Cache unable to write to "/var/nginx/html/codeigniter/writable/cache/". 找了好久&…...

.net framework 提示安装了 但是删除面板看不到

如果你在计算机上安装了.NET Framework&#xff0c;但在“控制面板”中找不到.NET Framework的相关条目&#xff0c;可能是因为.NET Framework的某些组件或特定版本未在“程序和功能”&#xff08;或旧版本的Windows中称为“程序和功能”&#xff09;列表中列出。这可能是正常情…...

flask-smorest 库

flask-smorest 简介 flask-smorest: 基于Flask/Marshmallow的REST API框架 flask-smorest 是一个用于创建于数据库无关的REST API的架库。 它使用Flask作为Web服务器&#xff0c;并使用marsmallow对数据进行序列化和反序列化。(类似于drf) 快速入门 flask-smorest对代码应…...

android WindowManager的简单使用

<?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"><uses-permission android:name"android.permis…...

Spark_Spark比mapreduce快的原因

Spark 为什么比 mapreduce 快? 最重要的3点&#xff0c; 数据缓存 : 中间结果可以缓存在内存中复用 资源管理 &#xff1a;executor task 管理&#xff0c;不同stage的task可以运行在同一个executor上 任务调度 : dag 对比多阶段mr 1.任务模型的优化&#xff08;DAG图对比…...

el-upload调用内部方法删除文件

从Element UI 的官方文档中&#xff0c; Upload 上传组组件提供了on-remove和before-remove的文件删除的钩子属性&#xff08;回调方法名&#xff09;&#xff0c;但如何调用组件删除方法&#xff08;让该方法删除本地上传文件列表以及触发这两个钩子&#xff09;并无相关说明。…...

无涯教程-JavaScript - CUBEKPIMEMBER函数

描述 该函数返回关键绩效指标(KPI)属性,并在单元格中显示KPI名称。 语法 CUBEKPIMEMBER (connection, kpi_name, kpi_property, [caption])争论 Argument描述Required/OptionalconnectionName of the connection to the cube - A text stringRequiredkpi_nameName of the K…...

代码随想录Day_52打卡

①、最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序…...

692. 前K个高频单词

题目来源&#xff1a;力扣 题目描述&#xff1a; 给定一个单词列表 words 和一个整数 k &#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c; 按字典顺序 排序。 示例 1&#xff1a; 输入:…...

介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用

Docker 是一个开源的容器化平台&#xff0c;可以让开发者将应用程序和其所依赖的组件&#xff08;如库、运行环境&#xff09;打包成一个可移植、自包含的容器。这个容器可以在任何支持 Docker 的环境中运行&#xff0c;包括开发、测试、生产等环境。Docker 的基本概念包括以下…...

C++:构建一个二叉树的代码

​#include <iostream>// 定义二叉树节点 struct BinaryTreeNode {int data;BinaryTreeNode* left;BinaryTreeNode* right;BinaryTreeNode(int val) : data(val), left(nullptr), right(nullptr) {} };// 构建二叉树 BinaryTreeNode* buildBinaryTree() {int val;std::ci…...

iOS 设置下载部分文件,如何获取完整文件的大小

在视频的需求中&#xff0c;遇到这样一个需求&#xff0c;播放一视频的时候&#xff0c;要预下载 后面10条视频&#xff0c;但是只下载后面十条视频的前面1M 实现方法 1 创建请求时设置cacheLength resource [[IdiotResource alloc] init];resource.requestURL task.request…...

如何助力金融贷款企业实现精准营销获客

无论是哪个行业&#xff0c;吸引客户都是核心。 许多公司的线下渠道面临着许多障碍&#xff0c;以至于他们不得不采用在线客户获取方法。受影响最大的行业之一是贷款行业。如何获得准确的贷款客户资源&#xff1f;如何赢得客户已经成为企业的一大痛点。 过去&#xff0c;信贷…...

html中的换行(\n)或回车(\r)符号不起作用的解决办法、br、white、space、pre、line

文章目录 前言html不解释空白字符CSS样式的影响特定的文本区域white-space 前言 如果您的HTML中的换行和回车符号&#xff08;\n和\r&#xff09;似乎不起作用&#xff0c;可能有几种可能的原因&#xff1a; html不解释空白字符 在HTML中&#xff0c;连续的空白字符&#xff0…...

SpringBoot+MyBatisPlus+MySql+vue2+elementUi的案例、java访问数据库服务、java提供接口服务

文章目录 前言后端关键代码前端关键代码完整代码 前言 1、项目不使用前后端分离。 2、在创建SpringBoot的时候要注意各个插件间的版本问题。 3、后端技术SpringBootMyBatisPlusMySql。 4、前端技术vue2elementUi。 后端关键代码 简单介绍 1、数据库名称ssm_db 2、表名称tbl_bo…...

设计模式入门(二)观察者模式

设计模式入门 本系列所有内容参考自《HeadFirst设计模式》。因为书中的代码是采用java语言写的&#xff0c;博主这里用C语言改写。 这里采用讲故事的方式进行讲解。若有错误之处&#xff0c;非常欢迎大家指导。 设计模式&#xff1a;模式不是代码&#xff0c;而针对设计问题的…...

列化复杂的xml对应的类

你能帮我写一个序列化复杂的xml对应的类吗? c#代码 好的,可以试着为一个复杂的XML生成对应的C#类。这里我就简单的XML为例: <Book><Name>Design Patterns</Name><Author>Erich Gamma</Author><Pages>395</Pages><Chapters>…...

什么是软件开发生命周期(SDLC)?

软件开发生命周期&#xff08;SDLC&#xff09;指的是从软件项目开始到最终交付的整个过程。它是软件开发过程的指导框架&#xff0c;用于规划、开发、测试、部署和维护软件系统。 SDLC包含了一系列阶段&#xff0c;每个阶段都有特定的任务、活动和产物。这些阶段通常包括以下…...

Anthropic代码泄露,AI江湖风云再起?

过去24小时&#xff0c;AI圈因Anthropic的两次泄露事件炸开了锅。Claude Code源码泄露&#xff0c;Mythos跑分也流出。这一系列事件不仅暴露了模型细节&#xff0c;还引发对Anthropic未来的诸多猜测。两次泄露&#xff0c;引发行业震动先是Claude Code源码意外泄露&#xff0c;…...

不用手动设置滤波参数,程序自动根据信号特征,匹配滤波参数,零基础也能抗干扰。

在智能仪器的世界里&#xff0c;我们经常面临一个尴尬的局面&#xff1a;实验室里算法跑得飞起&#xff0c;一到现场就被噪声淹没。今天&#xff0c;我将结合《智能仪器设计》中的自适应信号处理理念&#xff0c;带你手撸一个“傻瓜式”自适应滤波器。这个工具的目标很明确&…...

【IEEE TNNLS 2025】赋予大模型“跨院行医”的能力:基于全局与局部提示的医学图像泛化框架 (GLP) 解析

在医学图像分割的临床落地中&#xff0c;一个长期存在的痛点是**“领域偏移 (Domain Shift)”**。一个在A医院&#xff08;源域&#xff09;表现完美的深度学习模型&#xff0c;当部署到使用不同成像设备、不同扫描参数的B医院&#xff08;未知目标域&#xff09;时&#xff0c…...

5分钟快速掌握Bypass Paywalls Clean:终极内容解锁工具完整指南

5分钟快速掌握Bypass Paywalls Clean&#xff1a;终极内容解锁工具完整指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 你是否经常遇到想阅读优质文章却被付费墙阻挡的烦恼&#…...

2026 年 GEO 优化公司推荐:6家服务商综合实力对比分析

一、GEO 行业进入合规技术双轮驱动的爆发期IDC 最新发布的《2026年全球生成式引擎优化市场报告》显示&#xff0c;2026年全球 GEO&#xff08;生成式引擎优化&#xff09;市场规模将达 220 亿美元&#xff0c;年复合增长率高达 122%&#xff0c;中国市场规模预计突破 480 亿元&…...

Qwen2.5-14B-Instruct深度微调实录:像素剧本圣殿开源剧本创作指南

Qwen2.5-14B-Instruct深度微调实录&#xff1a;像素剧本圣殿开源剧本创作指南 1. 项目概览 像素剧本圣殿&#xff08;Pixel Script Temple&#xff09;是一款基于Qwen2.5-14B-Instruct大模型深度微调的专业剧本创作工具。这个开源项目将前沿AI技术与复古像素美学相结合&#…...

极验三代验证码全流程解析:从注册请求到ajax.php验证

1. 极验三代验证码技术架构解析 极验三代验证码作为当前主流的交互式安全验证方案&#xff0c;其技术架构设计体现了多重防御思想。整个验证流程采用分阶段验证机制&#xff0c;每个环节都设置了独立的安全校验点。从技术实现角度看&#xff0c;系统由前端SDK、验证逻辑引擎和风…...

Win10下MobSF安装避坑指南:从Python版本冲突到环境变量配置全解析

Win10下MobSF安装避坑指南&#xff1a;从Python版本冲突到环境变量配置全解析 移动应用安全测试已成为开发流程中不可或缺的一环。作为一款强大的开源工具&#xff0c;MobSF&#xff08;Mobile Security Framework&#xff09;因其全面的自动化分析能力备受开发者青睐。然而在…...

OpenClaw自动化流水线:Phi-3-vision处理图片转Excel报表

OpenClaw自动化流水线&#xff1a;Phi-3-vision处理图片转Excel报表 1. 为什么需要自动化报表生成 上周我收到财务同事发来的20张手机拍摄的销售数据表照片&#xff0c;要求整理成统一格式的Excel报表。手动录入数据花了整整3小时&#xff0c;期间还因为看错数字返工两次。这…...

Tencent Hunyuan3D-1.0模型蒸馏实践:从std版本压缩出移动端可用的轻量模型

Tencent Hunyuan3D-1.0模型蒸馏实践&#xff1a;从std版本压缩出移动端可用的轻量模型 【免费下载链接】Hunyuan3D-1 腾讯开源的Hunyuan3D-1项目&#xff0c;创新提出两阶段3D生成方法&#xff0c;实现快速、高质量的文本到3D和图像到3D转换&#xff0c;融合Hunyuan-DiT模型&am…...