首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在适配器kotlin中更新视图时如何正确使用Diff utils

在适配器kotlin中更新视图时如何正确使用Diff utils
EN

Stack Overflow用户
提问于 2021-10-21 18:11:42
回答 1查看 2.2K关注 0票数 0

嘿,我是新来的DiffUtil in adpater。我读了一些来自堆栈溢出的文章,google文档和一些文章。我正在努力理解areItemsTheSameareContentsTheSame回调 of DiffUtil,但是,我不清楚这意味着什么。我正在添加一些代码,请看一下。如果我做错了,请指导我。

GroupKey

代码语言:javascript
复制
data class GroupKey(
    val type: EnumType,
    val sender: Sender? = null,
    val close: String? = null
)

EnumType

代码语言:javascript
复制
enum class EnumType {
    A,
    B
}

发件人

代码语言:javascript
复制
data class Sender(
    val company: RoleType? = null,
    val id: String? = null
)

RoleType

代码语言:javascript
复制
data class RoleType(
    val name : String?= null
    val id: String? = null
)

集团

代码语言:javascript
复制
data class Group(
    val key: GroupKey,
    val value: MutableList<Item?>
)

我将我的列表传递给适配器,它是一个Group mutableList

代码语言:javascript
复制
var messageGroupList: MutableList<Group>? = null
..
val adapter = MainAdapter()
binding.recylerview.adapter = adapter
adapter.submitList(groupList)

在适配器中使用DiffUtil

MainAdapter.kt

代码语言:javascript
复制
class MainAdapter :ListAdapter<Group, RecyclerView.ViewHolder>(COMPARATOR) {

    companion object {
        private val COMPARATOR = object : DiffUtil.ItemCallback<Group>() {
            override fun areItemsTheSame(oldItem: Group, newItem: Group): Boolean {
                return oldItem == newItem
            }

            override fun areContentsTheSame(oldItem: Group, newItem: Group): Boolean {
                return ((oldItem.value == newItem.value) && (oldItem.key == newItem.key))
            }
        }
    }
.....
}

1.这里我需要比较的其他属性,如类型、发件人等。也在这个DiffUtil.ItemCallback中。

2.当使用==或===时,等于()怎么办?

3.如果我们比较int、boolean或String,我们使用==E 256还是其他什么?

在这个适配器中,我调用另一个具有在适配器中传递项列表的回收视图。

项目

代码语言:javascript
复制
data class Item(
    val text: String? = null,
    var isRead: Boolean? = null,
    val sender: Sender? = null,
    val id: Int? = null
)

NestedRecyclerView.kt

代码语言:javascript
复制
class NestedRecyclerView : ListAdapter<Item, IncomingMessagesViewHolder>(COMPARATOR) {

    companion object {
        private val COMPARATOR = object : DiffUtil.ItemCallback<Item>() {
            override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
                return oldItem.id == newItem.id
            }

            override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
                return ((oldItem.isRead == oldItem.isRead) &&
                        (oldItem.sender == newItem.sender) &&
                        (oldItem.text == oldItem.text))
            }
        }
    }
}

同样的问题,我也需要在这里比较发送者的其他属性。

areItemsTheSame中的4.需要比较id还是oldItem == newItem?

5.如何正确地更新适配器项。在普通的循环视图中,我们使用notifiyDataSetChanged.但是在函数中,我是否需要再次调用、submitList、函数,并且它会处理所有的事情?

代码语言:javascript
复制
adapter.submitList(groupList)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-21 19:10:57

问题1和4:

areItemsTheSame意味着这两个实例表示相同的数据项,即使某些内容可能不同。假设您有一个联系人列表,Jane的中间首字母已经更改,但是该行仍然应该表示相同的人员Jane。您的模型类可能有不同的实例,有一些不同的值,但它们应该表示相同的行。

因此,通常您只会比较旧的和新的项目之间的一件事,在本例中,每一项都是相同的。通常,如果您从数据库或API中获取数据,将有一些表示数据点的唯一ID,这就是您在areItemsTheSame中需要进行比较的全部内容。例如,oldItem.id == newItem.id

areContentsTheSame意味着,如果两个实例都显示在您的列表中,它们看起来将是相同的。因此,如果您使用的是data class,那么使用oldItem == newItem就足够了,因为数据类有一个比较每个属性的equals函数。

在您的项目回调代码中,您的areItemsTheSame看起来是正确的,但是您的areContentsTheSame过于复杂。因为Item是一个数据类,所以只需要直接比较这两个项。

代码语言:javascript
复制
override fun areContentsTheSame(oldItem: Item, newItem: Item) = oldItem == newItem

在您的组回调代码中,如果这是确定项目是否相同的有效方法,也许可以比较新旧项的GroupKeys。由于您只使用直接的==比较,当项目部分更改时,您可能会有一些视觉缺陷,如视图消失和重新出现,而不是简单地进行一些文本更改。

问题2你很少需要在Kotlin中使用===。它不仅检查两个项是否等效,而且还检查这两个项是否引用了内存中完全相同的实例。这完全不适合于DiffUtil.ItemCallback。

问题3 ==是比较任意两个对象的正确方法。在Kotlin中,即使是原语也应该这样进行比较,因为它们的行为就像对象一样。

问题5和ListAdapter,您应该始终使用submitList而不是notifyDataSetChangednotifyDataSetChanged将导致对所有视图进行毫无意义的刷新,并使使用ListAdapter和DiffUtil的目的落空。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69666866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档