ListAdapter SubmitList 已经有更新的项目,因此列表不会更新

问题描述 投票:0回答:1

我正在监听从数据库发出的流并尝试更新适配器数据,如下所示:

lifecycleScope.launchWhenCreated {
    presenter.data.buffer().collectLatest {
        val newList = it.toMutableList()
        adapter.data = newList
     }
}

当这个块被击中时,

adapter.data
已经有了更新的内容,因此
DiffUtil
不会更新列表,因为发出的数据的内容和
adapter.data
所具有的内容完全相同,包括我刚刚所做的更新。这主要发生在交替尝试中(第一次尝试不起作用,因为
adapter.data
已经拥有流发出的数据,第二次尝试则没有,所以它一次应用两个更新)

这是适配器中调用submitList的数据对象:

    var data: List<Messages> by Delegates.observable(emptyList()) { _, old, new ->
    submitList(new)}

这就是我发出数据的方式:

    val messageData = messageRepository.getMessages(id).map {
    //Mapping code
    returnList.toList()
  }

我可以确认,emit 总是首先被调用,这是我为adapter.data 赋值的唯一地方。我很奇怪为什么

adapter.data
在交替尝试分配之前已经有了更新的值

android kotlin kotlin-coroutines listadapter android-diffutils
1个回答
0
投票
  1. 修改Adapter的data属性 确保每次更新数据时 DiffUtil 都会收到对列表的新引用,即使内容没有更改。您可以通过在调用 SubmitList 之前创建一个新列表来实现此目的。
var data: List<Messages> by Delegates.observable(emptyList()) { _, old, new ->
    // Only submit the list if the contents have changed (or the reference is new)
    if (old != new) {
        submitList(new.toList()) // Force a new list reference even if contents are the same
    }
}
  1. 修改流量采集代码 在从流程中收集数据的代码中,请确保在设置数据之前始终使用新的列表引用。
lifecycleScope.launchWhenCreated {
    presenter.data.buffer().collectLatest {
        val newList = it.toMutableList() // Convert to mutable list to create a new reference
        adapter.data = newList
    }
}

通过将流数据转换为可变列表 (toMutableList()),您可以确保适配器接收新的列表引用,即使内容相同也是如此。这样,DiffUtil 将始终检测到某些内容发生了变化。

  1. 避免为相同的数据调用submitList 如果你不想在数据没有变化的情况下调用submitList,可以优化Delegates.observable块,使其在数据相同时跳过更新:
var data: List<Messages> by Delegates.observable(emptyList()) { _, old, new ->
    if (old != new) { 
        submitList(new.toList()) // Submit only if there's a difference
    }
}
  1. 考虑更有效地使用 DiffUtil.ItemCallback 如果您在适配器内使用 DiffUtil.ItemCallback,请确保正确实现它以比较列表项的内容。

例如:

class MessagesDiffCallback : DiffUtil.ItemCallback<Messages>() {
    override fun areItemsTheSame(oldItem: Messages, newItem: Messages): Boolean {
        return oldItem.id == newItem.id // Compare unique identifiers
    }

    override fun areContentsTheSame(oldItem: Messages, newItem: Messages): Boolean {
        return oldItem == newItem // Use content comparison (ensure Messages implements equals)
    }
}

尝试一下,让我知道它是否有效

© www.soinside.com 2019 - 2024. All rights reserved.