在适配器 kotlin 中更新视图时如何正确使用 Diff utils
How to proper way of using Diff utils when updating view in adapter kotlin
嘿,我是 Adpater 中 DiffUtil 的新手。我阅读了一些来自堆栈溢出的文章、google 文档和一些文章。我试图理解 callback of DiffUtil areItemsTheSame 和 areContentsTheSame 但是,我不清楚那是什么意思。我正在添加一些代码,请看一下。如果我做错了,请指导我。
组键
data class GroupKey(
val type: EnumType,
val sender: Sender? = null,
val close: String? = null
)
枚举类型
enum class EnumType {
A,
B
}
发件人
data class Sender(
val company: RoleType? = null,
val id: String? = null
)
角色类型
data class RoleType(
val name : String?= null
val id: String? = null
)
组
data class Group(
val key: GroupKey,
val value: MutableList<Item?>
)
我正在将我的列表传递给适配器,它是一个 Group mutableList
var messageGroupList: MutableList<Group>? = null
..
val adapter = MainAdapter()
binding.recylerview.adapter = adapter
adapter.submitList(groupList)
在适配器
中使用DiffUtil
MainAdapter.kt
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. 这里需要比较key other 属性 like type, sender etc . 也在这个 DiffUtil.ItemCallback.
里面
2. 何时使用 == 或 === 以及 等于()
3.如果我们比较int、boolean或String 我们使用 == 或者其他的 ?
在此适配器内,我正在调用另一个 Recyclerview,并在该适配器内传递 Item 列表。
项目
data class Item(
val text: String? = null,
var isRead: Boolean? = null,
val sender: Sender? = null,
val id: Int? = null
)
NestedRecyclerView.kt
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))
}
}
}
}
同样的问题我是否需要在这里也比较发件人的其他属性。
4. 在 areItemsTheSame 中,我需要比较 id 还是 oldItem == newItem 这个?
5. 如何正确更新我的适配器项目。在正常的 reyclerview 中,我们使用 notifiyDataSetChanged。但是在 diffutil 中,我是否需要再次调用 submitList 函数,它会处理所有事情?
adapter.submitList(groupList)
问题 1 和 4:
areItemsTheSame
表示两个实例表示相同的数据项,即使某些内容可能不同。假设您有一个联系人列表,并且 Jane 的中间名首字母已更改,但该行仍应代表同一个人 Jane。您的模型 class 可能有不同的实例,具有一些不同的值,但它们应该代表同一行。
因此,在这种情况下,通常您只会比较旧项目和新项目之间的一件事,这对每个项目来说都是一样的。通常,如果您从数据库或 API 获取数据,将会有一些唯一的 ID 代表一个数据点,这就是您需要在 areItemsTheSame
中进行比较的全部内容。例如,oldItem.id == newItem.id
.
areContentsTheSame
表示如果这两个实例分别显示在您的列表中,它们将看起来完全相同。因此,如果您使用 data class
,使用 oldItem == newItem
就足够了,因为数据 class 有一个 equals
函数,可以比较每个 属性.
在您的 Item 回调代码中,您的 areItemsTheSame
看起来是正确的,但您的 areContentsTheSame
过于复杂。由于Item是一个数据class,直接比较两个item即可
override fun areContentsTheSame(oldItem: Item, newItem: Item) = oldItem == newItem
在您的组回调代码中,也许您可以比较新旧项目的 GroupKeys,如果这是确定项目相同的有效方法的话。由于您仅使用直接 ==
比较,当项目部分更改时,您可能会遇到一些视觉缺陷,例如视图消失和重新出现,而不是简单地更改其中的一些文本。
问题 2
你应该很少在 Kotlin 中使用 ===
。它不仅检查两个项目是否等价,而且检查这两个项目是否引用内存中的完全相同的实例。它根本不适合 DiffUtil.ItemCallback。
问题 3
==
是比较任意两个对象的正确方法。在 Kotlin 中,即使是基元也应该以这种方式进行比较,因为它们的行为类似于对象。
问题 5
对于 ListAdapter,您应该始终使用 submitList
而不是 notifyDataSetChanged
。 notifyDataSetChanged
会导致所有视图的无意义刷新并破坏使用 ListAdapter 和 DiffUtil 的目的。
嘿,我是 Adpater 中 DiffUtil 的新手。我阅读了一些来自堆栈溢出的文章、google 文档和一些文章。我试图理解 callback of DiffUtil areItemsTheSame 和 areContentsTheSame 但是,我不清楚那是什么意思。我正在添加一些代码,请看一下。如果我做错了,请指导我。
组键
data class GroupKey(
val type: EnumType,
val sender: Sender? = null,
val close: String? = null
)
枚举类型
enum class EnumType {
A,
B
}
发件人
data class Sender(
val company: RoleType? = null,
val id: String? = null
)
角色类型
data class RoleType(
val name : String?= null
val id: String? = null
)
组
data class Group(
val key: GroupKey,
val value: MutableList<Item?>
)
我正在将我的列表传递给适配器,它是一个 Group mutableList
var messageGroupList: MutableList<Group>? = null
..
val adapter = MainAdapter()
binding.recylerview.adapter = adapter
adapter.submitList(groupList)
在适配器
中使用DiffUtilMainAdapter.kt
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. 这里需要比较key other 属性 like type, sender etc . 也在这个 DiffUtil.ItemCallback.
里面2. 何时使用 == 或 === 以及 等于()
3.如果我们比较int、boolean或String 我们使用 == 或者其他的 ?
在此适配器内,我正在调用另一个 Recyclerview,并在该适配器内传递 Item 列表。
项目
data class Item(
val text: String? = null,
var isRead: Boolean? = null,
val sender: Sender? = null,
val id: Int? = null
)
NestedRecyclerView.kt
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))
}
}
}
}
同样的问题我是否需要在这里也比较发件人的其他属性。
4. 在 areItemsTheSame 中,我需要比较 id 还是 oldItem == newItem 这个?
5. 如何正确更新我的适配器项目。在正常的 reyclerview 中,我们使用 notifiyDataSetChanged。但是在 diffutil 中,我是否需要再次调用 submitList 函数,它会处理所有事情?
adapter.submitList(groupList)
问题 1 和 4:
areItemsTheSame
表示两个实例表示相同的数据项,即使某些内容可能不同。假设您有一个联系人列表,并且 Jane 的中间名首字母已更改,但该行仍应代表同一个人 Jane。您的模型 class 可能有不同的实例,具有一些不同的值,但它们应该代表同一行。
因此,在这种情况下,通常您只会比较旧项目和新项目之间的一件事,这对每个项目来说都是一样的。通常,如果您从数据库或 API 获取数据,将会有一些唯一的 ID 代表一个数据点,这就是您需要在 areItemsTheSame
中进行比较的全部内容。例如,oldItem.id == newItem.id
.
areContentsTheSame
表示如果这两个实例分别显示在您的列表中,它们将看起来完全相同。因此,如果您使用 data class
,使用 oldItem == newItem
就足够了,因为数据 class 有一个 equals
函数,可以比较每个 属性.
在您的 Item 回调代码中,您的 areItemsTheSame
看起来是正确的,但您的 areContentsTheSame
过于复杂。由于Item是一个数据class,直接比较两个item即可
override fun areContentsTheSame(oldItem: Item, newItem: Item) = oldItem == newItem
在您的组回调代码中,也许您可以比较新旧项目的 GroupKeys,如果这是确定项目相同的有效方法的话。由于您仅使用直接 ==
比较,当项目部分更改时,您可能会遇到一些视觉缺陷,例如视图消失和重新出现,而不是简单地更改其中的一些文本。
问题 2
你应该很少在 Kotlin 中使用 ===
。它不仅检查两个项目是否等价,而且检查这两个项目是否引用内存中的完全相同的实例。它根本不适合 DiffUtil.ItemCallback。
问题 3
==
是比较任意两个对象的正确方法。在 Kotlin 中,即使是基元也应该以这种方式进行比较,因为它们的行为类似于对象。
问题 5
对于 ListAdapter,您应该始终使用 submitList
而不是 notifyDataSetChanged
。 notifyDataSetChanged
会导致所有视图的无意义刷新并破坏使用 ListAdapter 和 DiffUtil 的目的。