如何解决在Kotlin中使用ViewModel和LiveData实现滑动删除的实现
我想在RecyclerView中实现滑动以删除功能,该功能中填充了来自API的数据。
有一个ViewModel
类,并且数据已从API提取到ViewModel中的allOrders: MutableLiveData<MutableList<ModelClass>>
。 Fragment中的观察者在LiveData更改时更新RecyclerView适配器:
viewModel.allOrders.observe(viewLifecycleOwner,Observer {
adapter.submitList(it)
})
我想从allOrders: MutableLiveData<MutableList<ModelClass>>
删除RecyclerView中的刷卡项目,因此这是在ViewModel类中执行此操作的功能:
fun deleteItem(index: Int) {
_allOrders.value?.removeAt(index)
}
但是从MutableLiveData<MutableList>
中删除项目甚至都不会通知观察者。
使用以下方法实现此类功能的最佳做法是什么 Kotlin中的ViewModel和LiveData?
更新
我将 deleteItem 函数更改为此:
fun deleteItem(index: Int) {
_allOrders.value = _allOrders.value?.also { list ->
list.removeAt(index)
}
现在已通知观察者,但是adapter.submitList(it)
不会将RecyclerView更改为新列表。滚动RecyclerView抛出IndexOutOfBoundsException
。
解决方法
您可以在ViewModel中有一个“引用列表”并对其进行操作。删除该项目后,请更新列表并使用此列表更新LiveData:
class YourViewModel: ViewModel() {
private var ordersList = MutableList<ModelClass>()
val _allOrders = MutableLiveData<MutableList<ModelClass>>()
fun deleteItem(index: Int) {
ordersList.removeAt(index)
_allOrders.value = ordersList
}
}
如果您不需要Kotlin作用域函数also
,也可以不添加全局作用域列表,而只对LiveData发出的值进行操作:
fun deleteItem(index: Int) {
_allOrders.value = _allOrders.value?.also { list ->
list.removeAt(index)
}
}
,
您实现v-for="quest in exam[0].questions"
的方式绕过了LiveData类。您将获得对作为其值存储的List的引用,并直接对其进行操作,LiveData不会意识到数据发生了任何事情。
由于Kotlin是传递引用语言,所以LiveData持有的值只是对持有数组的内存的引用,这意味着如果更改数组的内容,{{1} }实际上并没有任何改变。
您必须在LiveData上设置一个新值,以便对其进行更新并通知观察者,对于List,您要么必须创建一个全新的List并将其设置为值,或执行以下操作:
deleteItem()
,
我遇到了同样的问题,submitList() 没有更新视图。找到解决方案 here
基本上,适配器类存储对当前列表的引用(称为 curList)。当使用 newList 调用 submitList 时,它会比较 curList 和 newList,如果它们引用相同的列表,它会默默地忽略更新视图。
在上述解决方案中,我们正在删除列表中的元素,因此引用没有改变。因此,当我们使用这个新列表调用 submitList 时,该函数会将其视为同一个列表,因此它会忽略更新视图。
一种解决方案是:
adapter.submitList(null);
adapter.submitList(it);
但这将再次在所有列表元素上调用 OnBindView,忽略 DiffUtilCallBack。
另一种是创建浅拷贝:
adapter.submitList(mutableListOf(it))
确保在列表发生变化的所有地方都以这种方式调用 submitList。
或使 allOrders: MutableLiveData<List<ModelClass>>
和:
fun deleteItem(index: Int) {
// minus() creates a new list automatically
_allOrders.value = _allOrders.value?.minus(_allOrders.value?.get(index))
}
这样就可以直接调用submitList(it)了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。