You need to enable JavaScript to run this app. Android ViewHolder未正确回收导致Bitmap驻留堆内存问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Android ViewHolder未正确回收导致Bitmap驻留堆内存问题求助

问题核心根源

你标记的几个传入ViewHolder的参数不是问题根源,内存暴涨由以下三个原因共同导致:

  • 图片加载绑定了错误的生命周期:你传入的是Fragment级别的viewLifecycleOwner,其生命周期远长于单个ViewHolder的存活周期。滚动过程中被回收的ViewHolder对应的图片加载请求不会被主动取消,所有请求都会执行完毕,产生的Bitmap没有对应的展示场景也无法及时回收,堆内存中就会堆积大量无效Bitmap实例。
  • ViewHolder复用阶段没有清理任务:ViewHolder被复用执行新的bind逻辑时,上一轮绑定触发的图片请求仍在运行,执行完成后会将Bitmap塞给已经被复用的ImageView,进一步增加无效Bitmap的数量,滚动频次越高,无效请求的数量就越大。
  • 双层内存缓存重复存储:你自行实现的Lru联系人头像缓存,和Coil/Glide默认开启的内存缓存各自存储了一份相同的Bitmap,同一张图片直接占用双倍内存,进一步推高了内存占用。

修复方案

  1. 主动回收ViewHolder对应的图片请求
    在Adapter中重写onViewRecycled方法,触发ViewHolder的资源释放逻辑:
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
    super.onViewRecycled(holder)
    if (holder is CustomerViewHolderPhoto) {
        holder.release()
    }
}

在CustomerViewHolderPhoto的release方法中取消当前ImageView的加载请求,清空引用的Drawable:

override fun release() {
    // 取消当前ImageView对应的未完成加载请求
    imageManager.cancelRequestForImageView(binding.imageViewCustomer)
    // 清空Bitmap引用,加速GC回收
    binding.imageViewCustomer.setImageDrawable(null)
}
  1. 解决缓存重复问题
    二选一即可:
  • 关闭图片库的内存缓存,以你自行实现的Lru缓存作为唯一内存缓存,比如Coil单次请求配置如下:
imageView.load(data) {
    memoryCachePolicy(CachePolicy.DISABLED)
}
  • 移除自行实现的Lru缓存,将lookupKey作为图片加载的唯一缓存Key,交由Coil/Glide统一处理内存缓存,从根源避免重复存储。
  1. 优化Bitmap复用逻辑
    检查你的ImageManager实现,避免每次加载都新建Bitmap实例,对接Coil/Glide的BitmapPool复用已回收的Bitmap内存空间,减少频繁的内存分配开销。

内容的提问来源于stack exchange,提问作者Andre Thiele

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 10:36:05