使用共享ViewModel在Activity与Fragment间向RecyclerView添加数据的覆盖问题
解决方案
问题根源
- Constants每次返回新列表实例:
getAlarmData()方法每次调用都会创建新的ArrayList<Alarm>,导致旧数据无法被保留,新添加的闹钟实际存在于临时列表中,Fragment重建或重新获取列表时旧数据丢失。 - 数据更新未通知Adapter:向列表添加新数据后,没有调用Adapter的更新方法,RecyclerView无法感知数据变化,不会刷新界面。
- 列表引用不一致:如果Fragment多次获取列表实例,Adapter持有的列表和当前操作的列表不是同一个对象,更新操作无法同步到Adapter。
修复步骤
1. 修改Constants为单例列表
将Constants中的列表改为全局单例,确保所有操作复用同一列表实例:
object Constants { // 使用lazy初始化单例列表,仅在首次访问时创建 val alarmList: ArrayList<Alarm> by lazy { val list = ArrayList<Alarm>() // 添加初始测试数据 list.add(Alarm("12 mai 1999","21:10", 1021,"")) list.add(Alarm("12 mai 1999","21:10", 1021,"")) list } }
2. 优化Fragment的观察与Adapter逻辑
确保Adapter持有单例列表的引用,并在数据添加后通知Adapter更新:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 获取全局单例列表 val alarmList = Constants.alarmList val itemAdapter = Adapter(alarmList) val recyclerView: RecyclerView = binding.recycleView recyclerView.layoutManager = LinearLayoutManager(context) recyclerView.adapter = itemAdapter // 观察LiveData,添加新闹钟并通知Adapter sharedViewModel.text.observe(viewLifecycleOwner) { newAlarm -> alarmList.add(newAlarm) // 通知Adapter在列表末尾插入新条目,比notifyDataSetChanged更高效 itemAdapter.notifyItemInserted(alarmList.size - 1) } }
3. 可选:封装Adapter的更新方法
为Adapter添加专门的添加数据方法,封装数据更新逻辑,提高代码可维护性:
class Adapter(private val alarmlist1: ArrayList<Alarm>) : RecyclerView.Adapter<Adapter.MyViewHolder>() { // 原有方法保持不变... // 添加新闹钟并通知RecyclerView更新 fun addAlarm(alarm: Alarm) { alarmlist1.add(alarm) notifyItemInserted(alarmlist1.size - 1) } }
此时Fragment中的观察逻辑可以简化为:
sharedViewModel.text.observe(viewLifecycleOwner) { newAlarm -> itemAdapter.addAlarm(newAlarm) }
内容的提问来源于stack exchange,提问作者Antonie Suciu
相关产品推荐
相关产品推荐

