在显式设置值之前,MutableLiveData 中的更改会反映在观察器中



在ViewModel中,我有一个MutableLiveData,其泛型类型是自定义对象列表。该对象具有可从 UI 更改的selected字段。现在,我正在使用RecyclerView来填充UI和DiffUtil.Callback来调度正确的更改。

选中 ViewHolder 中的复选框后,片段(包含回收器视图(中的回调会收到通知。然后调用 ViewHolder 中的方法来更改项目的selected值,然后调用setValue

片段

private fun observeViewModel() {
viewModel.data.observe(viewLifecycleOwner, Observer {
adapter.updateItems(items)
this.items = items
})
}
override fun onSelectionChange(position: Int) {
viewModel.reverseSelection(position)
}

视图模型

fun reverseSelection(index: Int) {
data.value?.let {
if (it.size > index) {
it[index].selected = !it[index].selected
data.value = it
}
}
}

回收器查看适配器

fun updateItems(items: List<T>) {
val diffCallback = BaseDiffCallback(this.items, items)
val diffResult = DiffUtil.calculateDiff(diffCallback, false)
this.items = items
diffResult.dispatchUpdatesTo(this)
}

问题是 DiffUtil 没有检测到任何更改,因为它看起来片段中的items字段和 ViewHolder 中的数据值指向内存中的同一对象。使用 log 语句,我注意到片段中的项目在对 ViewHolder 中的数据显式调用setValue之前和触发观察器之前已经反映了更改。

请问,如何在片段中的项目没有反映状态的情况下更改selection状态,直到我在 ViewHolder 中调用setValue


编辑

我非常感谢花时间为我的问题提供解决方案的好心用户。但是,由于我没有很好地解释我的问题,因此提出的解决方案对我不起作用。

我错过的关键细节之一是我正在使用数据绑定,模型的检查状态决定了ViewHolder中其他视图的状态。此外,我之前打了一个错字,reverseSelection不在ViewHolder中,而是ViewModel。最后,我将AdapterViewHolder用于其他数据模型。

因此,selected变量驻留在数据类中非常重要,否则,在查看 HashMap 或 Set 中的元素时会产生性能开销;检查是否选择了position处的项目。数据集可能非常大。此外,由于我正在将RecyclerView.AdapterViewHolder用于其他数据模型,因此我觉得使用HashMap或Set并不是最佳解决方案。

目前,我不再依赖 ViewHolder 来处理更改后的数据模型的传播。因此,新的更新是:

视图模型

fun reverseSelection(index: Int): Boolean {
return data.value?.let {
if (it.size > index) {
it[index].selected = !it[index].selected
true
} else false
} ?: false
}

片段

override fun onSelectionChange(position: Int) {
if (viewModel.reverseSelection(position)) {
adapter.notifyItemChanged(position, 0)
}
}

我不知道这是否是最好的解决方案,但我现在会凑合着用它。

在适配器中,我将创建一个哈希映射,该映射将存储所选项目的索引,而不是直接修改项目。这将确保对象不会被修改,但您还存储选定的索引。

DiffUtil 是一个类,它可以计算两个不同列表之间的差异,并输出将第一个列表转换为第二个列表的更新操作列表。 因此,如果您更改对同一列表执行数据更改,则不会调用 diffUtil 类。

您在 MutableLivedata 中观察到的变化是因为您在选择项目时更改了模型列表。因此,每当您观察到的任何值更新时,mutablelivedate 都会调用 onChange 方法来通知。

为了记录更改时的可选视图,您可以在模型类中为其创建一个变量,以便稍后访问整个对象。或者,您可以观察整个列表,因此每当列表被修改时,您都可以观察到 onChange(( 方法的变化。

创建一个包含选定项目位置的集合。当用户从 recycerview 中选择项时,如果集中不存在该项,请将该项添加到哈希集中,但如果存在,请从集中删除该项。然后通知适配器更新屏幕上的视图。现在,将哈希集作为参数传递给单击侦听器中的onSelectionChange()侦听器方法。

fun reverseSelection(index: Int) {
data.value?.let {
if (set.contains(it)) {
//Uncheck the checkbox
set.remove(it)
return
}
set.add(it)
//Check the checkbox
//Call the interface/listener method here and pass the hashset as a parameter to it. The set consist of the seletected positions.
//Notify the adapter by calling notifyAdapterSetChanged()
}
}

视图模型中不需要任何逻辑来反转所选项目。

相关内容

  • 没有找到相关文章

最新更新