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

Glide 图片缓存:异步更新 + 动画支持 + 自定义目录+自定义刷新时效

利用Glide把图片缓存到本地。并且可以自定义缓存时间(默认24小时),过期自动重新缓存。

  • 自动识别图片类型,缓存文件后缀正确
  • 支持自定义磁盘缓存地址
  • 支持设置缓存时间
  • 支持 GIF/WebP 动画自动播放
  • 异步缓存,不阻塞UI
  • 可选择下载完成后自动刷新 ImageView(默认 false)

。简单明了。

先引入Glide依赖:

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

然后,添加一个工具类来做这一切:GlideCacheHelper.kt:

import android.content.Context
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.target.ImageViewTarget
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL
import java.security.MessageDigest
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executorsobject GlideCacheHelper {private const val DEFAULT_CACHE_HOURS = 24Lprivate val executor: ExecutorService = Executors.newSingleThreadExecutor()/*** 加载图片,优先本地缓存,异步更新过期缓存** @param context 上下文* @param url 图片 URL* @param imageView ImageView* @param cacheHours 缓存有效时间(小时),<=0 表示默认24小时* @param cacheDir 自定义缓存目录,默认使用 context.cacheDir* @param autoRefresh 是否下载完成自动刷新 ImageView,默认 false*/fun loadImage(context: Context,url: String,imageView: ImageView,cacheHours: Long = DEFAULT_CACHE_HOURS,cacheDir: File? = null,autoRefresh: Boolean = false) {val expireTime = if (cacheHours <= 0) DEFAULT_CACHE_HOURS * 60 * 60 * 1000 else cacheHours * 60 * 60 * 1000val dir = cacheDir ?: context.cacheDirval cacheFile = getCacheFile(dir, url)// 先显示本地缓存(如果存在)if (cacheFile.exists()) {loadWithGlide(context, cacheFile, imageView)} else {// 没有本地缓存,先显示网络图片(Glide 默认缓存)Glide.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView)}// 异步下载更新缓存,如果过期或不存在if (!cacheFile.exists() || isExpired(cacheFile, expireTime)) {executor.execute {val downloadedFile = downloadImage(url, cacheFile)if (autoRefresh && downloadedFile != null) {imageView.post { loadWithGlide(context, downloadedFile, imageView) }}}}}// 使用 Glide 加载文件,支持 GIF/WebP 动画和 PNG 透明背景private fun loadWithGlide(context: Context, file: File, imageView: ImageView) {val ext = file.extension.lowercase()when (ext) {"gif" -> {Glide.with(context).asGif().load(file).diskCacheStrategy(DiskCacheStrategy.NONE).into(object : ImageViewTarget<GifDrawable>(imageView) {override fun setResource(resource: GifDrawable?) {imageView.setImageDrawable(resource)resource?.start()}})}"webp" -> {Glide.with(context).asGif().load(file).diskCacheStrategy(DiskCacheStrategy.NONE).into(object : ImageViewTarget<GifDrawable>(imageView) {override fun setResource(resource: GifDrawable?) {imageView.setImageDrawable(resource)resource?.start()}})}else -> {Glide.with(context).load(file).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView)}}}// 下载图片到指定文件,返回实际保存的文件private fun downloadImage(urlString: String, file: File): File? {return try {val url = URL(urlString)val conn = url.openConnection() as HttpURLConnectionconn.connectTimeout = 10000conn.readTimeout = 15000conn.connect()if (conn.responseCode == HttpURLConnection.HTTP_OK) {val type = conn.contentTypeval ext = getExtension(type)val targetFile = File(file.parent, file.name + ext)val inputStream: InputStream = conn.inputStreamval fos = FileOutputStream(targetFile)val buffer = ByteArray(1024)var len: Intwhile (inputStream.read(buffer).also { len = it } != -1) {fos.write(buffer, 0, len)}fos.flush()fos.close()inputStream.close()conn.disconnect()targetFile} else {conn.disconnect()null}} catch (e: Exception) {e.printStackTrace()null}}// 根据 MIME 类型获取扩展名private fun getExtension(mimeType: String?): String {return when {mimeType == null -> ".jpg"mimeType.contains("png", true) -> ".png"mimeType.contains("gif", true) -> ".gif"mimeType.contains("webp", true) -> ".webp"else -> ".jpg"}}// 获取缓存文件路径(不带扩展名)private fun getCacheFile(cacheDir: File, url: String): File {val fileName = md5(url)return File(cacheDir, fileName)}// 判断文件是否过期private fun isExpired(file: File, cacheExpireTime: Long): Boolean {val now = System.currentTimeMillis()val lastModified = file.lastModified()return now - lastModified > cacheExpireTime}// MD5生成文件名,保证唯一private fun md5(string: String): String {return try {val digest = MessageDigest.getInstance("MD5")val bytes = digest.digest(string.toByteArray())val hexString = StringBuilder()for (b in bytes) {val h = Integer.toHexString(0xFF and b.toInt())if (h.length < 2) hexString.append("0")hexString.append(h)}hexString.toString()} catch (e: Exception) {e.printStackTrace()string.hashCode().toString()}}
}

使用方法:

// 默认缓存 24 小时,默认缓存目录,不自动刷新
GlideCacheHelper.loadImage(this, "https://example.com/test.webp", imageView)// 自定义缓存 12 小时,自定义缓存目录,不刷新 ImageView
val customDir = File(getExternalFilesDir(null), "myCache")
GlideCacheHelper.loadImage(this, "https://example.com/test.png", imageView, 12, customDir)// 自定义缓存 6 小时,自定义目录,下载完成自动刷新 ImageView
GlideCacheHelper.loadImage(this, "https://example.com/test.gif", imageView, 6, customDir, true)
http://www.dtcms.com/a/536046.html

相关文章:

  • SWAT模型应用
  • 界面控件DevExpress WPF v25.1 - 官宣支持Avalonia XPF
  • HarmonyOS应用日志HiLog:从基础使用到高级调试技术
  • 系统架构设计师备考第55天——数据库设计融合物联网层次架构案例分析
  • 加查网站建设乌海seo
  • 北京金港建设股份有限公司网站wordpress缓存清理
  • Deepseek大模型结合Chrome搜索爬取2025AI投资趋势数据
  • 基于 ComfyUI 的 Stable Diffusion 本地部署与使用教程(Windows + CUDA12.0)
  • HTTPS 端口,443 之外的那些坑与排查实战
  • Stable Diffusion 短视频制作算力需求与优化策略研究
  • ComfyUI本地部署Stable Diffusion:核心组件(Python、PyTorch、CUDA)版本与显卡配置全指南
  • Adobe Pro DC裁剪PDF流程介绍
  • 如何编写 Chrome 插件(Chrome Extension)
  • 怎样做网站吸引人深圳网站seo优化排名公司
  • 比wordpress更好的网站程序外贸高端网站建设
  • Qt QML Q_DECLARE_METATYPE宏的作用浅解
  • PyTorch 中 Tensor 交换维度(transpose、permute、view)详解
  • WebGL低端设备优化全攻略
  • 网站顶部素材校园文创产品设计
  • 无界微前端学习和使用
  • FPGA DDR3实战(十一):基于DDR3的高速故障录播系统(三)—— 地址管理与故障定位机制
  • 自定义协议、序列化与守护进程:构建可靠后端服务
  • 【FPGA】时序逻辑计数器——Verilog实现
  • 示范专业网站建设wordpress 添加二级
  • 【LeetCode】88. 合并两个有序数组
  • Redis键过期策略深度剖析:惰性删除与定期删除的完美平衡
  • 【紧急救援】MySQL root密码忘记?一键重置脚本和全平台解决方案
  • Redis Commander:一款基于Web、免费开源的Redis管理工具
  • 云南省住房和城乡建设局网站做投标的在什么网站找信息
  • 操作系统5.3.4 磁盘的管理