You need to enable JavaScript to run this app. RecyclerView适配器替换Kotlin合成导入为ViewBinding时出现视图刷新异常问题
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView适配器替换Kotlin合成导入为ViewBinding时出现视图刷新异常问题

核心问题根因

你把ViewBinding实例定义成了适配器层级的全局lateinit变量,这是导致数据绑定异常的根本原因。

  • RecyclerView会在需要新Item时多次调用onCreateViewHolder,每次调用都会覆盖这个全局binding的引用。
  • 当RecyclerView复用已有ViewHolder触发onBindViewHolder时,这个全局binding已经指向了最后一次创建的ViewHolder对应的绑定对象,根本不是当前要绑定的holder对应的视图实例。
  • 调试时你看到的“值已经被正确写入”,实际是写到了最后一次创建的、可能不在当前屏幕上的ViewHolder对应的控件上,当前屏幕显示的控件根本没有被赋值,最终就出现了“逻辑写了正确值,但界面显示旧数据”的错觉。
  • 之前用findViewById能正常工作,是因为它始终基于当前holder传入的视图树查找控件,不受全局binding引用错乱的影响。
修正实现步骤
  1. 删除适配器中定义的全局lateinit var binding: FinapiBankItemBinding变量。ViewBinding实例必须和单个ViewHolder的生命周期绑定,不能跨ViewHolder共享。
  2. 改造ViewHolder的构造逻辑,让它直接持有对应的ViewBinding实例,而不是只传root视图:
    class FinApiBankItemViewHolder(
        val itemBinding: FinapiBankItemBinding
    ) : RecyclerView.ViewHolder(itemBinding.root)
    
  3. 调整onCreateViewHolder的inflate逻辑,使用局部变量接收Binding实例,同时补全inflate的必要参数(避免Item布局尺寸异常):
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): FinApiBankItemViewHolder {
        val itemBinding = FinapiBankItemBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return FinApiBankItemViewHolder(itemBinding)
    }
    
  4. 重构onBindViewHolder和视图构建逻辑,所有视图操作都通过当前holder持有的binding实例完成,完全替代findViewById:
    override fun onBindViewHolder(
        holder: FinApiBankItemViewHolder,
        position: Int
    ) {
        if (data == null || data.size <= position) return
        val currentItem = data[position]
        buildView(holder.itemBinding, currentItem)
    }
    
    private fun buildView(itemBinding: FinapiBankItemBinding, item: FinApiBank) {
        itemBinding.bankNameTextView.text = item.name
        itemBinding.bicTextView.text = item.bic
        itemBinding.root.setOnClickListener {
            parentViewModel.getAndNavWebform(item.externalId!!)
        }
    }
    
额外注意点
  • 不要在适配器作用域缓存任何和单个Item视图相关的状态,所有和ViewHolder强绑定的对象都要放在ViewHolder类内部,跟着ViewHolder的复用流程走。
  • 之前的inflate调用只传了LayoutInflater,没有绑定父布局、也没有设置attachToRoot=false,长期使用可能会出现Item布局宽度/高度失效的问题,按上面的写法补全参数就能解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 16:24:03