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的内存缓存。

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

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

相关文章

读word模板批量生成制式文件

文章目录 1、Maven依赖2、.docx或.doc格式的word模板准备3、读word模板&#xff0c;批量替换代码域&#xff0c;生成文件&#xff0c;demo4、结果展示 1、Maven依赖 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagre…

nnUNet v2数据准备及格式转换 (二)

如果你曾经使用过nnUNet V1&#xff0c;那你一定明白数据集的命名是有严格要求的&#xff0c;必须按照特定的格式来进行命名才能正常使用。 这一节的学习需要有数据&#xff0c;如果你有自己的数据&#xff0c;可以拿自己的数据来实验&#xff0c;如果没有&#xff0c;可以用十…

两个pdf文件合并为一个怎么操作?分享pdf合并操作步骤

不管是初入职场的小白&#xff0c;还是久经职场的高手&#xff0c;都必须深入了解pdf&#xff0c;特别是关于pdf的各种操作&#xff0c;如编辑、合并、压缩等操作&#xff0c;其中合并是这么多操作里面必需懂的技能之一&#xff0c;但是很多人还是不知道两个pdf文件合并为一个怎…

ChatGPT⼊门到精通(4):ChatGPT 为何⽜逼

⼀、通⽤型AI 在我们原始的幻想⾥&#xff0c;AI是基于对海量数据的学习&#xff0c;锻炼出⼀个⽆所不知⽆所不能的模 型&#xff0c;并借助计算机的优势&#xff08;计算速度、并发可能&#xff09;等碾压⼈类。 但我们⽬前的AI&#xff0c;不管是AlphaGo还是图像识别算法&am…

解决Debian系统通过cifs挂载smb后,中文目录乱码问题

解决Debian系统通过cifs挂载smb后&#xff0c;中文目录乱码问题 //$smb_server/share /mnt/nas_share cifs credentials/root/.smbcredentials,iocharsetutf8 0 0默认通过以上命令挂载smb&#xff0c;但是在查看文件目录时&#xff0c;中文乱码 解决问题方式&#xff1a; de…

MR混合现实汽车维修情景实训教学演示

MR混合现实技术应用于汽车维修课堂中&#xff0c;能够赋予学生更加真实&#xff0c;逼真地学习环境&#xff0c;让学生在情景体验中不断提高自己的专业能力。 MR混合现实汽车维修情景实训教学演示具体体现在&#xff1a; 1. 虚拟维修指导&#xff1a;利用MR技术&#xff0c;可…

企业架构LNMP学习笔记9

nginx配置文件定义php-fpm服务&#xff1a; 编写测试文件&#xff1a; vim /usr/local/nginx/html/index.php 内容&#xff1a; <?phpphpinfo(); 在nginx的配置文件中配置&#xff1a; 修改配置文件&#xff0c;告知nginx如果收到.php结尾的请求&#xff0c;交由给php-…

【数据结构篇】线性表1 --- 顺序表、链表 (万字详解!!)

前言&#xff1a;这篇博客我们重点讲 线性表中的顺序表、链表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列... 线性表在逻辑上是…

mac软件安装后打开软件显示损坏

#mac传输安装包后安装后打开软件显示损坏处理方式 以postman为例&#xff0c;输入前面的代码&#xff0c;打开访达&#xff0c;把有问题的软件拉到命令行窗口&#xff0c;确认即可 sudo xattr -r -d com.apple.quarantine /Applications/Postman.app sudo xattr -r -d com.ap…

如何中mac上安装多版本python并配置PATH

摘要 mac 默认安装的python是 python3&#xff0c;但是如果我们需要其他python版本时&#xff0c;该怎么办呢&#xff1f; 例如&#xff1a;需要python2 版本&#xff0c;如果使用homebrew安装会提示没有python2。同时使用python --version 会发现commond not found。 所以本…

MySQL中表的设计

在MySQL中表的设计&#xff0c;需要一定的经验才能理解&#xff0c;由于笔者目前在读中&#xff0c;理解不是很深刻&#xff0c;仅根据自己的想法外界的一些参考资料做出下述文字描述&#xff0c;一些错误&#xff0c;请大佬及时指正~~ 在本篇文章中&#xff0c;介绍一点简单粗…

RocketMQ(消息中间件)

目录 一、为什么会出现消息中间件&#xff1f; 二、消息中间件是干嘛的&#xff1f; 三、应用解耦 四、流量削峰 五、异步处理 1.串行方式&#xff1a; 2.并行方式&#xff1a; 3.引入消息队列&#xff1a; 六、RocketMQ的架构及概念 一、为什么会出现消息中间件&#…

小程序快速备案助手代备案小程序开发

小程序快速备案助手代备案小程序开发 用户注册与登录&#xff1a;用户可以通过手机号或其他方式进行注册和登录&#xff0c;以便进行备案相关操作。备案信息填写&#xff1a;用户可以填写小程序的备案信息&#xff0c;包括小程序名称、小程序服务类目、域名等。备案材料上传&a…

Python钢筋混凝土结构计算.pdf-混凝土构件计算

计算原理&#xff1a; 代码实现&#xff1a; #钢筋混凝土参数 def c_hrb(): global fcuk,HRB,Ec,fc,ft,ftk,Es,fy,fyp,fyk global a1,epsilon_cu fcukEcfcftftk0.0 HRBEsfyfypfyk0.0 #矩形应力图系数a1&#xff0c;C50以下为1.0 a11.0 #正截面混凝土极限压应变epsilon_cu&#…

使用element-ui中的el-table回显已选中数据时toggleRowSelection报错

最近在写一个后台&#xff0c;需要在表格中多选&#xff0c;然后点击编辑按钮的时候&#xff0c;需要回显已经选中的表单项 <el-table v-loading"loading" :data"discountList" :row-key"(row) > row.id" refmultipleTable selection-cha…

Wireshark流量分析例题

1.题目要求&#xff1a; 1.黑客攻击的第一个受害主机的网卡IP地址 2.黑客对URL的哪一个参数实施了SQL注入 3.第一个受害主机网站数据库的表前缀&#xff08;加上下划线例如abc&#xff09; 4.第一个受害主机网站数据库的名字 看到题目SQL注入&#xff0c;那就首先过滤http…

智能化新十年,“全栈智能”定义行业“Copilot智能助手”

“智能化转型是未来十年中国企业穿越经济周期的利器”&#xff0c;这是联想集团执行副总裁兼中国区总裁刘军在去年联想创新科技大会上做出的判断&#xff0c;而2023年正值第四次工业革命第二个十年的开端&#xff0c;智能化是第四次工业革命的主题。2023年初&#xff0c;基于谷…

垃圾回收 - 引用计数法

GC原本是一种“释放怎么都无法被引用的对象的机制”。那么人们自然而然就会想到&#xff0c;可以让所有对象事先记录下“有多少程序引用了自己”。让各对象知道自己的“人气指数”&#xff0c;从而让没有人气的对象自己消失&#xff0c;这就是引用计数法。 1、计数器 计数器表…

personalized image enhancement 调研

Personalized Image Enhancement Using Neural Spline Color Transforms 这是TIP期刊 2020年的一篇论文&#xff0c;首先提出了一个能预测曲线的网络&#xff0c;预测一些锚点&#xff0c;根据锚点插值出连续的曲线&#xff0c;然后用曲线对raw image进行retouching。然后提出了…

【强化学习】MDP马尔科夫链

基本元素 状态集&#xff1a;表示智能体所处所有状态的全部可能性的集合。类似的集合&#xff0c;行为集&#xff0c;回报集决策&#xff1a;规定我在某个状态下&#xff0c;我做出某个action马尔可夫链&#xff1a;学术上来说是无记忆性质。说白了就是我只在乎我目前的状态。…