Glide 加载刷新闪动,自定义Transformations 必须实现的方法

本文主要是介绍Glide 加载刷新闪动,自定义Transformations 必须实现的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

我们使用Glide加载图片,使用自定义对Transformations 转换器的时候,都忽略了定制变换必须实现的方法:

  updateDiskCacheKeyequals() / hashCode()!

官网这么说明的:

为了让内存缓存正常地工作你是否必须实现 equals() 和 hashCode() 方法。很不幸,即使你没有复写这两个方法,BitmapTransformation 和 Transformation 也能通过编译,但这并不意味着它们能正常工作。

当我们重写这几个方法,刷新加载Glide 的时候图片会闪动一下,网上提供的各种解决Glide 加载图片出现闪动,什么设置tag,取消默认动画,没设置缓存等等解决方案都不可靠,可能是以前Glide 4.0 一下的版本解决方案吧,并且网上提供的大多数转换器是没有重写 updateDiskCacheKey、 equals() / hashCode()! 这几个方法的,导致我们Copy 过去使用的时候不能正常工作。

下面说说Transformations:
引用官网原文解决方案:http://bumptech.github.io/glide/doc/transformations.html

内置类型

Glide 提供了很多内置的变换,包括:

CenterCrop
FitCenter
CircleCrop

应用

通过 RequestOptions 类可以应用变换:

默认变换

RequestOptions options = new RequestOptions();
options.centerCrop();Glide.with(fragment).load(url).apply(options).into(imageView);

大多数内置的变换都有静态的 import ,这是为 API 的流畅性考虑的。例如,你可以通过静态方法应用一个 FitCenter 变换:

import static com.bumptech.glide.request.RequestOptions.fitCenterTransform;Glide.with(fragment).load(url).apply(fitCenterTransform()).into(imageView);

如果你正在使用 Generated API ,那么这些变换方法已经被内联了,所以使用起来甚至更为轻松:

GlideApp.with(fragment).load(url).fitCenter().into(imageView);

可以查阅 Options 页来获得更多 RequestOption 的相关信息。

多重变换
默认情况下,每个 transform() 调用,或任何特定转换方法(fitCenter(), centerCrop(), bitmapTransform() etc)的调用都会替换掉之前的变换。

如果你想在单次加载中应用多个变换,请使用 MultiTransformation 类。

使用 generated API:

Glide.with(fragment).load(url).transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation()).into(imageView);

或结合使用快捷方法和 generated API:

GlideApp.with(fragment).load(url).transforms(new FitCenter(), new YourCustomTransformation()).into(imageView);

请注意,你向 MultiTransformation 的构造器传入变换参数的顺序,决定了这些变换的应用顺序。

定制变换

尽管 Glide 提供了各种各样的内置 Transformation 实现,如果你需要额外的功能,你也可以实现你自己的 Transformation。

BitmapTransformation
如果你只需要变换 Bitmap,最好是从继承 BitmapTransformation 开始。BitmapTransformation 为我们处理了一些基础的东西,例如,如果你的变换返回了一个新修改的 Bitmap ,BitmapTransformation将负责提取和回收原始的 Bitmap。

一个简单的实现看起来可能像这样:

public class FillSpace extends BitmapTransformation {private static final String ID = "com.bumptech.glide.transformations.FillSpace";private static final String ID_BYTES = ID.getBytes(STRING_CHARSET_NAME);@Override
public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {return toTransform;}return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, /*filter=*/ true);
}@Override
public void equals(Object o) {return o instanceof FillSpace;
}@Override
public int hashCode() {return ID.hashCode();
}@Override
public void updateDiskCacheKey(MessageDigest messageDigest)throws UnsupportedEncodingException {messageDigest.update(ID_BYTES);
}

}

尽管你的 Transformation 将几乎确定比这个示例更复杂,但它应该包含了相同的基本元素和复写方法。

必需的方法

请特别注意,对于任何 Transformation 子类,包括 BitmapTransformation,你都有三个方法你 必须 实现它们,以使得磁盘和内存缓存正确地工作:

equals()
hashCode()
updateDiskCacheKey

如果你的 Transformation 没有参数,通常使用一个包含完整包限定名的 static final String 来作为一个 ID,它可以构成 hashCode() 的基础,并可用于更新 updateDiskCacheKey() 传入的 MessageDigest。如果你的 Transformation 需要参数而且它会影响到 Bitmap 被变换的方式,它们也必须被包含到这三个方法中。

例如,Glide 的 RoundedCorners 变换接受一个 int,它决定了圆角的弧度。它的equals(), hashCode() 和 updateDiskCacheKey 实现看起来像这样:

  @Overridepublic boolean equals(Object o) {if (o instanceof RoundedCorners) {RoundedCorners other = (RoundedCorners) o;return roundingRadius == other.roundingRadius;}return false;}@Overridepublic int hashCode() {return Util.hashCode(ID.hashCode(),Util.hashCode(roundingRadius));}@Overridepublic void updateDiskCacheKey(MessageDigest messageDigest) {messageDigest.update(ID_BYTES);byte[] radiusData = ByteBuffer.allocate(4).putInt(roundingRadius).array();messageDigest.update(radiusData);}

原来的 String 仍然保留,但 roundingRadius 被包含到了三个方法中。这里,updateDiskCacheKey 方法还演示了你可以如何使用 ByteBuffer 来包含基本参数到你的 updateDiskCacheKey 实现中。

不要忘记 equals() / hashCode()!
值得重申的一点是,为了让内存缓存正常地工作你是否必须实现 equals()hashCode() 方法。很不幸,即使你没有复写这两个方法,BitmapTransformationTransformation 也能通过编译,但这并不意味着它们能正常工作。我们正在探索一些方案,以使在 Glide 的未来版本中,使用默认的 equals() 和 hashCode 方法将抛出一个编译时错误。

Glide中的特殊行为

重用变换

Transformation 的设计初衷是无状态的。因此,在多个加载中复用 Transformation 应当总是安全的。创建一次 Transformation 并在多个加载中使用它,通常是很好的实践。

ImageView的自动变换

在Glide中,当你为一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。如果 scaleType 是 CENTER_CROP , Glide 将会自动应用 CenterCrop 变换。如果 scaleType 为 FIT_CENTER 或 CENTER_INSIDE ,Glide会自动使用 FitCenter 变换。

当然,你总有权利覆写默认的变换,只需要一个带有 Transformation 集合的 RequestOptions 即可。另外,你也可以通过使用 dontTransform() 确保不会自动应用任何变换。

自定义资源

因为 Glide 4.0 允许你指定你将解码的资源的父类型,你可能无法确切地知道将会应用何种变换。例如,当你使用 asDrawable() (或就是普通的 with() ,因为 asDrawable() 是默认情形)来加载 Drawable 资源时,你可能会得到 BitmapDrawable 子类,也有可能得到 GifDrawable 子类。

为了确保你添加到 RequestOptions 中的任何变换都会被使用,Glide将 Transformation 添加到一个Map中保存,其Key为你提供变换的资源类型。当资源被成功解码时,Glide使用这个Map来取回对应的 Transformation 。

Glide可以将 Bitmap Transformation应用到 BitmapDrawable , GifDrawable , 以及 Bitmap 资源上,因此通常你只需要编写和应用 Bitmap Transformation 。然而,如果你添加了额外的资源类型,你可能需要考虑派生 RequestOptions 类,并且,在内置的这些 Bitmap Transformations 之外,你还需要为你的自定义资源类型提供一个 Transformation 。

这篇关于Glide 加载刷新闪动,自定义Transformations 必须实现的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1079886

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操