使用Glide加载固定URL图片时如何在新图加载时显示缓存并更新缓存?
问题原因
Glide的缓存键由资源URL、签名参数、请求参数(尺寸、变换等)共同计算生成。你在updateImage方法中使用ObjectKey(System.currentTimeMillis())作为动态签名,相当于每次拉新请求的缓存键都不同,新下载的图片会存储到对应当前时间戳的独立缓存键下,和loadImage方法中使用默认签名的请求的缓存键完全不匹配,因此后续读缓存永远只能拿到第一次加载的旧图片。
修复方案
方案1:通过HTTP头强制刷新(推荐)
利用HTTP标准缓存控制头强制拉取最新资源,不需要修改签名参数,Glide会自动将新资源覆盖原URL对应的缓存,无需额外处理。
修改后的代码如下:
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.Headers import com.bumptech.glide.load.model.LazyHeaders // loadImage 方法不需要修改 fun loadImage(context: Context, imageView: ImageView, url: String?) { Glide.with(context) .asBitmap() .load(url) .onlyRetrieveFromCache(true) .into(object : CustomTarget<Bitmap>() { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { updateImage(context, imageView, url, resource) } override fun onLoadFailed(errorDrawable: Drawable?) { updateImage(context, imageView, url, null) } override fun onLoadCleared(placeholder: Drawable?) {} }) } private fun updateImage(context: Context, imageView: ImageView, url: String?, placeholder: Bitmap?) { url ?: return // 构造带Cache-Control头的请求地址,强制拉取最新资源 val glideUrl = GlideUrl(url, object : LazyHeaders.Builder() { override fun build(): Headers { return Headers.Builder() .add("Cache-Control", "no-cache") .build() } }.build()) Glide.with(context) .setDefaultRequestOptions(RequestOptions().timeout(30000)) .load(glideUrl) .placeholder(BitmapDrawable(context.resources, placeholder)) .dontAnimate() .into(imageView) }
方案2:手动同步缓存(适合服务器不支持缓存头的场景)
如果服务器无法适配缓存头控制,可以保留原有拉新逻辑,在新图片下载完成后手动写入原URL对应的缓存:
private fun updateImage(context: Context, imageView: ImageView, url: String?, placeholder: Bitmap?) { url ?: return Glide.with(context) .asBitmap() .setDefaultRequestOptions(RequestOptions().timeout(30000)) .load(url) .signature(ObjectKey(System.currentTimeMillis())) .placeholder(BitmapDrawable(context.resources, placeholder)) .dontAnimate() .into(object : CustomTarget<Bitmap>() { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { // 先更新UI展示新图 imageView.setImageBitmap(resource) // 手动将新图写入原URL对应的缓存 Glide.with(context) .downloadOnly() .load(url) .into(object : CustomTarget<File>() { override fun onResourceReady(cacheFile: File, transition: Transition<in File>?) { // 把新下载的bitmap写入缓存文件 runCatching { val outputStream = FileOutputStream(cacheFile) resource.compress(Bitmap.CompressFormat.PNG, 100, outputStream) outputStream.flush() outputStream.close() } } override fun onLoadCleared(placeholder: Drawable?) {} }) } override fun onLoadCleared(placeholder: Drawable?) {} }) }
逻辑验证
修改后可以满足你的所有需求:
- 启动时优先读取缓存中的旧图片展示
- 后台自动拉取服务器最新图片
- 新图片拉取完成后自动覆盖原有缓存
- 界面同步更新为最新图片
内容的提问来源于stack exchange,提问作者BArtWell
相关产品推荐
相关产品推荐

