RecyclerView数据未更新:批量修改unit属性后界面无反馈
问题描述
我正在实现一个功能,通过切换按钮批量修改RecyclerView列表项的unit属性。项目采用MVVM架构,业务逻辑在Repository层执行。经调试确认,Repository中List内所有item的unit已成功修改,但为ViewModel的_items.value赋值后,界面仍无变化,无法确定问题所在。
相关代码
WorkoutSetInfo
data class WorkoutSetInfo( @PrimaryKey(autoGenerate = true) val id: Long = 0, val set: Int, var weight: String = "0", var reps: String = "0", var unit: WorkoutUnit = WorkoutUnit.kg, val parentWorkoutId: Long = 0 )
Repository
class WriteDetailRepository(val dao: WorkoutDao) { private var setInfoList = arrayListOf(WorkoutSetInfo(set = 1)) // fixed set 1 private var updatedList = listOf<WorkoutSetInfo>() get() = setInfoList.toList() fun changeUnit(unit: WorkoutUnit) { updatedList = setInfoList.map { setInfo -> setInfo.copy(unit = unit) } } fun add() { val item = WorkoutSetInfo(set = setInfoList.size + 1) setInfoList.add(item) updatedList = setInfoList.toList() } fun getList() : List<WorkoutSetInfo> = updatedList }
ViewModel
class WriteDetailViewModel( private val repository: WriteDetailRepository ): ViewModel() { private var _items: MutableStateFlow<List<WorkoutSetInfo>> = MutableStateFlow(repository.getList()) val items = _items.asStateFlow() fun changeUnit(unit: WorkoutUnit) { repository.changeUnit(unit) _items.value = repository.getList() } fun addSet() { viewModelScope.launch(Dispatchers.IO) { repository.add() _items.value = repository.getList() // here } } }
Fragment
class WriteDetailFragment : Fragment() { ... private val viewModel: WriteDetailViewModel by viewModels { WriteDetailViewModelFactory( (requireActivity().application as WorkoutApplication).writeDetailRepo ) } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = FragmentWriteDetailBinding.inflate(inflater, container, false) binding.apply { ... addSet.setOnClickListener { viewModel.addSet() } unitToggle.addOnButtonCheckedListener { _, checkedId, isChecked -> if(isChecked) { when(checkedId) { R.id.kg -> viewModel.changeUnit(WorkoutUnit.kg) R.id.lb -> viewModel.changeUnit(WorkoutUnit.lbs) } } } } return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.items.collect { list -> // list value does not change adapter.submitList(list) } } } } }
问题分析与修复
核心问题
Repository中updatedList的自定义getter逻辑导致了问题:你在changeUnit里给updatedList赋值了修改后的新列表,但updatedList的getter被硬编码为返回setInfoList.toList()——也就是原始未修改的列表副本,后续调用getList()时,拿到的始终是原始数据,ViewModel和界面自然感知不到变化。
修复方案
方案1:移除自定义getter,直接维护更新后的列表
修改Repository逻辑,确保getList()返回真正修改后的列表:
class WriteDetailRepository(val dao: WorkoutDao) { private var setInfoList = arrayListOf(WorkoutSetInfo(set = 1)) private var updatedList: List<WorkoutSetInfo> = setInfoList.toList() fun changeUnit(unit: WorkoutUnit) { updatedList = setInfoList.map { setInfo -> setInfo.copy(unit = unit) } } fun add() { val item = WorkoutSetInfo(set = setInfoList.size + 1) setInfoList.add(item) updatedList = setInfoList.toList() } fun getList() : List<WorkoutSetInfo> = updatedList }
方案2:简化逻辑,直接修改原列表(更简洁)
利用data class的copy()方法直接更新原列表元素,无需额外维护updatedList:
class WriteDetailRepository(val dao: WorkoutDao) { private val setInfoList = mutableListOf(WorkoutSetInfo(set = 1)) fun changeUnit(unit: WorkoutUnit) { setInfoList.replaceAll { it.copy(unit = unit) } } fun add() { val item = WorkoutSetInfo(set = setInfoList.size + 1) setInfoList.add(item) } fun getList() : List<WorkoutSetInfo> = setInfoList.toList() }
额外优化建议
changeUnit方法仅做内存操作,无需放在Dispatchers.IO线程执行,ViewModel中可直接调用- 确保RecyclerView的Adapter正确实现DiffUtil,让
submitList能精准识别列表变化并更新界面
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

