You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:28:38