Glide抛出IllegalStateException:无法获取已回收Bitmap尺寸问题求助
解决Glide加载RecyclerView项背景时的"Cannot obtain size for recycled Bitmap"错误
这个问题我之前在做带模糊背景的RecyclerView时也碰到过,本质是Glide尝试访问已被系统回收的Bitmap尺寸导致的——RecyclerView的列表项会被复用,加上模糊背景涉及Bitmap的额外处理,滚动后返回时,之前的Bitmap可能已经被回收,但Glide的请求还在持有引用,就触发了这个异常。下面给你几个针对性的解决方案:
1. 优化普通背景的加载逻辑
你现在的代码是先通过AppCompatResources.getDrawable拿到Drawable再传给Glide,这会绕开Glide的资源管理机制。直接让Glide加载资源ID,它能更好地处理缓存和生命周期绑定:
fun AppCompatImageView.loadImage(resId: Int) { Glide.with(context) .load(resId) // 直接传入资源ID,让Glide内部处理Drawable创建 .into(this) }
2. 用Glide Transformation实现模糊背景(核心修复)
自己处理Bitmap模糊很容易出现生命周期不匹配的问题,建议用Glide的Transformation来实现模糊,这样Glide会全权负责Bitmap的回收和复用:
首先定义一个模糊Transformation:
class BlurTransformation(private val blurRadius: Int) : Transformation<Bitmap> { override fun transform( context: Context, resource: Resource<Bitmap>, outWidth: Int, outHeight: Int ): Resource<Bitmap> { val originalBitmap = resource.get() // 先缩小Bitmap减少模糊计算量,同时避免大内存占用 val scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, originalBitmap.width / 2, originalBitmap.height / 2, true) // 用RenderScript实现高效模糊(也可以替换成你自己的模糊逻辑) val rs = RenderScript.create(context) val inputAllocation = Allocation.createFromBitmap(rs, scaledBitmap) val outputAllocation = Allocation.createTyped(rs, inputAllocation.type) val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)) blurScript.setRadius(blurRadius.toFloat()) blurScript.setInput(inputAllocation) blurScript.forEach(outputAllocation) outputAllocation.copyTo(scaledBitmap) rs.destroy() return BitmapResource.obtain(scaledBitmap) ?: resource } override fun updateDiskCacheKey(messageDigest: MessageDigest) { // 给模糊效果设置唯一缓存键,确保不同半径的模糊能正确缓存 messageDigest.update("glide_blur_$blurRadius".toByteArray()) } }
然后修改模糊背景的加载代码:
Glide.with(mContext) .load(yourBackgroundResId) // 直接传资源ID或URL .apply(RequestOptions() .override(backgroundWidth, backgroundHeight) .transform(BlurTransformation(25))) // 传入你需要的模糊半径,比如25 .into(yourBackgroundImageView)
3. 回收列表项时取消Glide请求
在RecyclerView Adapter的onViewRecycled方法里,主动取消ImageView的Glide请求,避免引用已被回收的视图或Bitmap:
override fun onViewRecycled(holder: YourListViewHolder) { super.onViewRecycled(holder) // 取消对应ImageView的Glide加载请求 Glide.with(holder.itemView.context).clear(holder.backgroundImageView) }
关键注意点
- 永远不要手动回收Glide处理过的Bitmap,Glide有自己的Bitmap池和缓存机制,手动回收会导致它访问已被释放的资源
- 如果模糊效果需要自定义参数,确保在Transformation的
updateDiskCacheKey里加入这些参数,避免缓存混淆
内容的提问来源于stack exchange,提问作者AndroidRuntimeException
相关产品推荐
相关产品推荐

