安卓Glide加载失败时点击按钮重新加载图片

需求

假设此时已经用load指定一个url: String,又用into指定了一个img: ImageView开始加载,但是网络突然中断,导致图片加载失败。在这种情况下,想要通过点击一个Button重新加载。

kotlin 复制代码
Glide.with(context).load(url)
	.placeholder(loadingBitmap)
	.into(img) // 失败后将保持 loadingBitmap

分析1

自然的想法是直接添加一个按钮,在失败时重复执行加载过程:

kotlin 复制代码
button.setOnClickListener {
	Glide.with(context).load(url)
		.placeholder(loadingBitmap)
		.into(img) // 失败后将保持 loadingBitmap
}

但是这样做每次点击按钮都会重新执行一遍Glide的构建流程,浪费处理资源。

分析2

在Glide处理时增加一个监听器,只有onLoadFailed亦即加载失败时,才将按钮设为可点击,并且撤销之前的监听器。同时,为按钮增加一个监控变量,确保其只被点击了一次,避免重复加载(退化为分析1)。

代码比较复杂,这里略去不写。

分析3

实际上Glide自身存在控制资源重新加载的方式,即Target。因此,不需要任何重初始化,只要调用Target的相关函数刷新加载请求即可。

解决方案

将分析3编写为一个简单的类如下。

kotlin 复制代码
class RequestReloadingButtonListener<T>(private val button: Button) : RequestListener<T> {
	var mTarget: Target<T>? = null
	init {
		button.apply { post {
			setOnClickListener { mTarget?.request?.apply {
				clear()		// 取消上次请求
				begin()		// 异步开始新请求
			} }
		} }
	}
	override fun onLoadFailed(
		e: GlideException?,
		model: Any?,
		target: Target<T>,
		isFirstResource: Boolean
	): Boolean {
		button.visibility = View.VISIBLE	// 显示重加载按钮
		mTarget = target					// 记录请求目标
		return false
	}
	override fun onResourceReady(
		resource: T & Any,
		model: Any,
		target: Target<T>?,
		dataSource: DataSource,
		isFirstResource: Boolean
	): Boolean {
		button.visibility = View.GONE		// 隐藏重加载按钮
		return false
	}
}

这样一来,通过如下代码即可实现加载失败时显示重加载按钮,用户点击后重新加载:

kotlin 复制代码
Glide.with(context).load(url)
	.placeholder(loadingBitmap)
	.addListener(RequestReloadingButtonListener(button))
	.into(img)
相关推荐
时间静止不是简史3 小时前
生产事故排查:Redis 宕机导致补偿队列消费线程死亡,通话录音未上送业务平台
java·redis
2301_32241428046 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
金銀銅鐵8 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
福建佰胜张工8 小时前
SMC 薄型气爪 MHF2-16D1 深度解析:平行开闭、低剖面结构在自动化装配中的选型与落地
java·服务器·安全·自动化
catoop9 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
system_error_x9 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
吹什么轩9 小时前
MySQL:数据类型
android·adb
酷炫码神9 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
驭渊的小故事10 小时前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客10 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es