Android开发:RecyclerView创建后按钮点击失效及Todo展示问题
问题分析与解决
核心问题
- 保存按钮点击后数据已写入数据库,但RecyclerView未刷新,导致你误以为点击事件未触发
- 当前Adapter无法动态更新数据,每次获取数据都新建Adapter,既低效又无法复用实例
修复步骤
1. 修改CustomAdapter,支持动态更新数据
给Adapter添加更新数据集的方法,避免重复创建新Adapter:
class CustomAdapter(private var dataSet: List<Todo>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView = view.findViewById(R.id.textView3) } override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.recycler_view_row, viewGroup, false) return ViewHolder(view) } override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { viewHolder.textView.text = dataSet[position].description } override fun getItemCount() = dataSet.size // 添加更新数据的方法 fun updateData(newData: List<Todo>) { dataSet = newData notifyDataSetChanged() } }
2. 修改MainActivity,复用Adapter并在保存后刷新数据
将Adapter设为成员变量,保存数据后重新获取最新列表并更新Adapter:
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var db: TodoDatabase private lateinit var recyclerView: RecyclerView // 把Adapter设为成员变量,方便后续更新 private lateinit var adapter: CustomAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) db = TodoDatabase.getInstance(this) setContentView(binding.root) val save: Button = binding.button val todo: TextInputEditText = binding.todoInput // 初始化RecyclerView基础配置,只执行一次 recyclerView = binding.recyclerView recyclerView.layoutManager = LinearLayoutManager(this) adapter = CustomAdapter(emptyList()) recyclerView.adapter = adapter // 加载初始数据 lifecycleScope.launch { loadUncheckedTodos() } save.setOnClickListener { val todoText = todo.text.toString() if (todoText.isNotEmpty()) { lifecycleScope.launch { save(todoText) todo.text?.clear() // 保存完成后重新加载数据并刷新列表 loadUncheckedTodos() } } } } private suspend fun loadUncheckedTodos() { val todos = db.todoDao().getUnchecked() adapter.updateData(todos) } private suspend fun save(todo: String) { db.todoDao().upsert(Todo(id = null, description = todo, checked = false)) } }
3. 关键说明
- 按钮点击事件实际已触发,只是之前没有刷新RecyclerView导致页面无变化,误以为点击无效
- Room的suspend方法会自动切换到后台线程执行,无需手动指定Dispatcher,lifecycleScope默认在主线程启动协程,调用suspend方法时会自动切到IO线程,执行完成后回到主线程更新UI,这部分逻辑是安全的
- 初始化RecyclerView的LayoutManager和Adapter只需要执行一次,避免重复操作影响性能
内容的提问来源于stack exchange,提问作者Dylan Maurits
相关产品推荐
相关产品推荐

