Android开发中,使用 Glide 加载图片资源是一个很常见的方案。但是最近我遇到了一个十分诡异的问题:使用 Glide 加载本地 R.mipmap 资源时,加载的图片竟然不是我传入的资源 ID,而是上一次加载的另一张图片
通过排查和实验证实,该问题的根本原因在于:Glide 对本地资源的缓存机制,结合 mipmap 类型资源的特殊性,导致了图片错乱加载。
本文将记录这个问题的详细分析过程、验证方法及最终解决方案。
问题背景:
我定义了一个枚举类 ImageTypeEnum 来管理多种类型图标及其背景图资源:
enum class ImageTypeEnum(val id: Int, val iconRes: Int, val backgroundRes: Int) {
CUSTOM(0, R.mipmap.ic_custom, -1),
TYPE_A(1, R.mipmap.ic_type_a, R.mipmap.bg_type_a),
TYPE_B(2, R.mipmap.ic_type_b, R.mipmap.bg_type_b),
TYPE_C(3, R.mipmap.ic_type_c, R.mipmap.bg_type_c),
TYPE_D(4, R.mipmap.ic_type_d, R.mipmap.bg_type_d)
}
在 UI 中我希望根据当前项动态设置背景图,使用了如下 Glide 加载方式:
Glide.with(this)
.load(currentItem.backgroundRes)
.into(object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
binding.containerLayout.background = resource
}
override fun onLoadCleared(placeholder: Drawable?) {}
})
问题现象
当我切换到 TYPE_B 项时,原本应显示的 bg_type_b 背景图,却意外地加载成了 bg_type_a 的图片。
而当我将代码改为使用系统原生方式设置背景图时,一切又正常了:
binding.containerLayout.setBackgroundResource(currentItem.backgroundRes)
说明资源 ID 本身是正确的,问题只出现在 Glide 加载流程中。
排查思路与验证过程
1. 检查资源 ID 是否正确
通过日志打印 currentItem.backgroundRes,确认其确实是 R.mipmap.bg_type_b,与实际期望值一致。
资源 ID 本身没问题。
2. 怀疑 Glide 缓存干扰
Glide 默认会启用内存缓存和磁盘缓存,考虑是否因为资源 ID 相近或内容类似导致缓存误用。
我修改 Glide 加载方式以禁用缓存:
Glide.with(this)
.load(currentItem.backgroundRes)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(object : CustomTarget<Drawable>() {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
binding.containerLayout.background = resource
}
override fun onLoadCleared(placeholder: Drawable?) {}
})
结果:问题消失了。背景图加载正确,说明问题确实来自 Glide 缓存逻辑。
3. 资源类型 mipmap 的使用不当
我把所有图片资源放在了 res/mipmap 目录,而非 drawable。但 mipmap 主要用于应用图标,它在构建过程中有独特处理方式,不推荐用作界面图像资源。
Glide 加载 mipmap 资源时可能无法完全区分 ID 或文件路径,从而导致缓存错乱。
最终解决方案
基于以上结论,最终做了如下优化:
- 将资源文件移至
res/drawable; - 不再使用 Glide 加载本地背景图;
- 使用更安全的原生设置方式:
binding.containerLayout.setBackgroundResource(currentItem.backgroundRes)