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

如何给RecyclerView的ViewHolder添加Binding以获取tvTodoTitle和cbDone

为RecyclerView的ViewHolder添加ViewBinding获取控件的解决方案

一、核心实现步骤(使用ViewBinding)

首先确保项目已启用ViewBinding,在模块级build.gradle(或build.gradle.kts)中添加配置:

android {
    buildFeatures {
        viewBinding true
    }
}

接下来修改TodoAdapter代码,将ViewBinding集成到ViewHolder中:

  1. 重构ViewHolder类
    将原本接收View的ViewHolder,替换为接收对应item布局的自动生成Binding类(此处为ItemTodoBinding,由item_todo.xml自动生成):
class TodoViewHolder(val binding: ItemTodoBinding) : RecyclerView.ViewHolder(binding.root)
  1. 修改onCreateViewHolder方法
    不再直接inflate布局View,而是通过Binding类的inflate方法创建实例并传入ViewHolder:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
    val binding = ItemTodoBinding.inflate(LayoutInflater.from(parent.context), parent, false)
    return TodoViewHolder(binding)
}
  1. 优化onBindViewHolder逻辑
    通过holder.binding直接访问布局内控件(tvTodoTitle和cbDone),无需再通过itemView查找:
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
    val curTodo = todos[position]
    with(holder.binding) {
        // 修正原代码笔误:etTodoTitle应为tvTodoTitle,且需设置text属性
        tvTodoTitle.text = curTodo.title
        cbDone.isChecked = curTodo.isChecked
        toggleStrikeThrough(tvTodoTitle, curTodo.isChecked)
        
        cbDone.setOnCheckedChangeListener { _, isChecked ->
            toggleStrikeThrough(tvTodoTitle, isChecked)
            // 修正原逻辑错误:直接赋值为当前选中状态即可
            curTodo.isChecked = isChecked
        }
    }
}

二、完整修改后的TodoAdapter代码

package com.example.todoit

import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.todoit.data.Todo
import com.example.todoit.databinding.ItemTodoBinding

class TodoAdapter(
    private val todos: MutableList<Todo>,
) : RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {

    class TodoViewHolder(val binding: ItemTodoBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
        val binding = ItemTodoBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return TodoViewHolder(binding)
    }

    fun addTodo(todo: Todo) {
        todos.add(todo)
        notifyItemInserted(todos.size - 1)
    }

    fun deleteDoneTodos() {
        todos.removeAll { todo -> todo.isChecked }
        notifyDataSetChanged()
    }

    private fun toggleStrikeThrough(tvTodoTitle: androidx.appcompat.widget.AppCompatTextView, isChecked: Boolean) {
        if (isChecked) {
            tvTodoTitle.paintFlags = tvTodoTitle.paintFlags or STRIKE_THRU_TEXT_FLAG
        } else {
            tvTodoTitle.paintFlags = tvTodoTitle.paintFlags and STRIKE_THRU_TEXT_FLAG.inv()
        }
    }

    override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
        val curTodo = todos[position]
        with(holder.binding) {
            tvTodoTitle.text = curTodo.title
            cbDone.isChecked = curTodo.isChecked
            toggleStrikeThrough(tvTodoTitle, curTodo.isChecked)

            cbDone.setOnCheckedChangeListener { _, isChecked ->
                toggleStrikeThrough(tvTodoTitle, isChecked)
                curTodo.isChecked = isChecked
            }
        }
    }

    override fun getItemCount(): Int {
        return todos.size
    }
}

三、替代方案(不使用ViewBinding)

若暂时不想使用ViewBinding,可在ViewHolder中提前通过findViewById缓存控件,避免重复查找:

class TodoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val tvTodoTitle: TextView = itemView.findViewById(R.id.tvTodoTitle)
    val cbDone: CheckBox = itemView.findViewById(R.id.cbDone)
}

// 在onBindViewHolder中直接调用缓存的控件
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
    val curTodo = todos[position]
    holder.tvTodoTitle.text = curTodo.title
    holder.cbDone.isChecked = curTodo.isChecked
    // 后续逻辑同上
}

额外修复点(原代码中的小问题)

  1. MainActivity中binding.etTodoTitle.toString()需改为binding.etTodoTitle.text.toString(),否则获取的是TextView对象字符串而非输入文本
  2. MainActivity中todoDB未初始化,需在onCreate中添加todoDB = TodoDataBase.getInstance(this)(假设数据库类有单例实现)
  3. TodoAdapter中lambda表达式语法错误:todo -和isChecked -需改为todo ->和isChecked ->

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:54:09