首页 > 解决方案 > MutableLiveData 的变化在显式设置值之前反映在观察者中

问题描述

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

当检查查看持有人中的复选框时,通知片段中的回调(包含循环电视)。然后调用 ViewHolder 中的一个方法来更改selecteditem 的值,然后调用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
        }
    }

}

RecyclerView 适配器

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

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

请问,在我调用ViewHolder之前,如何在selection没有 Fragment 中的项目反映状态的情况下更改状态?setValue


编辑

我非常感谢那些花时间为我的问题提供解决方案的好心用户。但是,因为我没有很好地解释我的问题,所以建议的解决方案对我不起作用。

我错过的关键细节之一是我正在使用数据绑定,并且模型的检查状态决定了ViewHolder. 另外,我之前犯了一个错字,reverseSelection不在ViewHolderbutViewModel中。最后,我将AdapterViewHolder用于其他数据模型。

因此,selected变量驻留在数据类中非常重要,否则在查看 HashMap 或 Set 中的元素时会产生性能开销;检查是否position选择了项目。数据集可能非常大。此外,因为我使用RecyclerView.AdapterandViewHolder用于其他数据模型,所以我觉得使用 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)
        }
    }

我不知道这是否是最好的解决方案,但我现在就去做。

标签: androidkotlinviewmodelandroid-livedata

解决方案


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


推荐阅读