如何使用Delegates.Observable获得新旧数据之间的差异



获取差异而不是返回整个值以供UI重新绘制不是更好吗?

var collection: List<String> by 
Delegates.observable(emptyList()) { prop, old, new ->
notifyDataSetChanged()    
}

有可能提高它的效率吗?

您应该看看DiffUtil类

DiffUtil是一个实用程序类,它可以计算两个列表之间的差异,并输出将第一个列表转换为第二个列表的更新操作列表。

DiffUtil使用Eugene W.Myers的差分算法来计算将一个列表转换为另一个列表的最小更新次数。Myers的算法不处理移动的项目,因此DiffUtil对结果进行第二次传递,以检测移动的项目。

如果列表很大,则此操作可能需要相当长的时间,因此建议您在后台线程上运行此操作

基本上,您必须使用两个列表实现DiffUtil.Callback

data class MyPojo(val id: Long, val name: String)
class DiffCallback(
private val oldList: List<MyPojo>,
private val newList: List<MyPojo>
) : DiffUtil.Callback() {
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].id == newList[newItemPosition].id
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].name == newList[newItemPosition].name
}
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
// Implement method if you're going to use ItemAnimator
return super.getChangePayload(oldItemPosition, newItemPosition)
}
}

然后你必须通知使用它的适配器。例如,你可以在适配器中创建一个函数,如下所示:

fun swap(items: List<myPojo>) {
val diffCallback = ActorDiffCallback(this.items, items)
val diffResult = DiffUtil.calculateDiff(diffCallback)
this.items.clear()
this.items.addAll(items)
diffResult.dispatchUpdatesTo(this)
}

在您的情况中,假设collection是您的适配器的成员:

var collection: List<String> by Delegates.observable(emptyList()) { prop, old, new ->
val diffCallback = DiffCallback(old, new)
val diffResult = DiffUtil.calculateDiff(diffCallback)
diffResult.dispatchUpdatesTo(this)
}

一些参考文献:

  • https://developer.android.com/reference/android/support/v7/util/DiffUtil
  • https://proandroiddev.com/diffutil-is-a-must-797502bc1149
  • https://github.com/mrmike/DiffUtil-sample/

最新更新