如何将Adapter数据传递至Activity?解决已完成任务数同步问题
问题解决步骤
1. 修复TodoAdapter中的逻辑错误
你的Adapter同时设置了setOnCheckedChangeListener和setOnClickListener,会导致事件冲突,且状态更新、列表操作逻辑存在问题,先修改这部分:
class TodoAdapter( private var todos: MutableList<Todo>, private var dones: MutableList<Todo>, private val onDoneListChanged: () -> Unit // 添加回调,通知外部列表变化 ): RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() { class TodoViewHolder(ItemTodoBinding: ItemTodoBinding): RecyclerView.ViewHolder(ItemTodoBinding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder { val layoutInflater = LayoutInflater.from(parent.context) val itemTodoBinding = ItemTodoBinding.inflate(layoutInflater, parent, false) return TodoViewHolder(itemTodoBinding) // 移除原代码中重复的return语句 } private fun toggleStrikeThrough(tvTodoTitle: TextView, 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] holder.itemView.apply{ val tvTodoTitle = findViewById<TextView>(R.id.tvTodoTitle) val tvTodoDate = findViewById<TextView>(R.id.tvTodoDate) val cbDone = findViewById<CheckBox>(R.id.cbDone) tvTodoTitle.text = curTodo.title tvTodoDate.text = curTodo.date cbDone.isChecked = curTodo.isChecked toggleStrikeThrough(tvTodoTitle, curTodo.isChecked) // 整合监听逻辑,避免事件冲突 cbDone.setOnCheckedChangeListener { _, isChecked -> toggleStrikeThrough(tvTodoTitle, isChecked) curTodo.isChecked = isChecked // 直接赋值为当前选中状态,无需取反 if(isChecked){ // 选中时将任务移至已完成列表 todos.remove(curTodo) dones.add(curTodo) notifyItemRemoved(position) // 用精确的通知提升性能 onDoneListChanged() // 触发回调通知MainActivity更新按钮 } else { // 取消选中时将任务移回待办列表(可选逻辑,按需保留) dones.remove(curTodo) todos.add(curTodo) notifyItemInserted(todos.size - 1) onDoneListChanged() } } } } override fun getItemCount(): Int = todos.size }
2. 修改MainActivity,接收回调并更新按钮文本
在MainActivity中初始化Adapter时传入回调,确保每次已完成列表变化时更新按钮显示:
class MainActivity : AppCompatActivity() { private lateinit var todoAdapter:TodoAdapter private lateinit var binding: ActivityMainBinding private var todos: MutableList<Todo> = mutableListOf() private var dones: MutableList<Todo> = mutableListOf() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 初始化Adapter并传入回调 todoAdapter = TodoAdapter(todos, dones) { updateDoneButtonText() } binding.rvTodoItems.adapter = todoAdapter binding.rvTodoItems.layoutManager = LinearLayoutManager(this) binding.btnAddTodo.setOnClickListener{ NewTaskSheet().show(supportFragmentManager,"NewTaskTag") } supportFragmentManager.setFragmentResultListener("requestKey",this){ _, bundle -> val newTodo = bundle.getSerializable("bundleKey") as Todo todos.add(newTodo) todoAdapter.notifyItemInserted(todos.size - 1) updateDoneButtonText() // 新增任务后可按需更新按钮 } binding.btnTodoDone.setOnClickListener{ val intent = Intent(this, SecondActivity::class.java) startActivity(intent) } // 初始化时设置一次按钮文本 updateDoneButtonText() } // 提取更新按钮文本的方法,方便重复调用 private fun updateDoneButtonText(){ binding.btnTodoDone.text = "Done(${dones.size})" } }
关键问题说明
- 按钮文本未实时更新:原代码仅在
onCreate中设置一次按钮文本,后续已完成列表变化时未重新赋值,导致始终显示0。通过updateDoneButtonText方法,在列表变化时调用即可实时更新数量。 - Adapter事件冲突:同时设置两种点击监听会导致触发逻辑混乱,整合为一个监听即可解决。
- 列表变化感知:通过给Adapter添加回调接口,让MainActivity能感知已完成列表的变化,从而触发按钮文本更新。
内容的提问来源于stack exchange,提问作者Владислава Черкасова
相关产品推荐
相关产品推荐

