2

我的 recyclerview 中有无尽的滚动,所以当有新数据时它会更新。我正在使用 DiffUtil 更新 recyclerview 中的数据。DiffUtil 确实会更新数据,但只要有更新数据,recyclerview 就会滚动到顶部,看起来就像“使用 notifydatasetchanged()”。这是我的 DiffUtil 和我的适配器来更新数据。

class ProductDiffUtil(
    val oldProductList: List<ProductModel>, val newProductList: List<ProductModel>
) : DiffUtil.Callback() {

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldProductList[oldItemPosition].id == newProductList[newItemPosition].id
    }

    override fun getOldListSize(): Int = oldProductList.size

    override fun getNewListSize(): Int = newProductList.size

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldProductList[oldItemPosition] == newProductList[newItemPosition]
    }

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        return super.getChangePayload(oldItemPosition, newItemPosition)
    }
}

这是我更新数据的适配器

fun addProductList(productList: List<ProductModel>?) {
        val diffResult = DiffUtil.calculateDiff(ProductDiffUtil(this.productList, productList!!))
        this.productList.addAll(productList)
        diffResult.dispatchUpdatesTo(this)
    }

请帮我解决一下这个。当我使用 notifyItemRangeChanged() 时它工作正常......所以我应该使用什么来更新 recyclerview 中的数据以获得最佳实践。

https://drive.google.com/open?id=1SapXW2wusmTpyGCRA9fa0aSLCYNL1fzN

4

3 回答 3

3

您仅将先前的内容与新项目进行比较,而不是与添加了所有项目的列表进行比较。

想象一下 ifthis.productList是 current 1,2,3,而 new productListis 4,5,6。当你跑

DiffUtil.calculateDiff(ProductDiffUtil(this.productList, productList!!)

它将142to5等进行比较,并得出结论,一切都发生了变化,并且没有添加新项目。(注意:这是对 DiffUtil 算法的过度简化,但用于说明这一点)

相反,如果你想使用 DiffUtil:

val oldList = ArrayList(productList)
this.productList.addAll(productList)
val diffResult = DiffUtil.calculateDiff(ProductDiffUtil(oldList, productList!!)
diffResult.dispatchUpdatesTo(this)

或者,由于您确切知道添加了多少项目以及在何处添加,因此只需使用notifyItemRangeInserted并避免复制:

val oldSize = this.productList.size
this.productList.addAll(productList)
notifyItemRangeInserted(oldSize, productList.size)
于 2020-02-20T21:16:45.793 回答
0

考虑创建一个通用的 diffUtil 类,而不是为每个适配器创建它。

fun <T>diffList(oldList: List<T>, newList: List<T>, sameItem: (a: T, b: T) -> Boolean): DiffUtil.DiffResult {
val callback: DiffUtil.Callback = object : DiffUtil.Callback() {
    override fun getOldListSize(): Int {
        return oldList.size
    }

    override fun getNewListSize(): Int {
        return newList.size
    }

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return sameItem(oldList[oldItemPosition], newList[newItemPosition])
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldList[oldItemPosition] == newList[newItemPosition]
    }
}

return DiffUtil.calculateDiff(callback) }

您可以像这样在适配器中使用它:

 fun setItems(products: List<Product>) {
    val oldList = productList
    productList = products
    diffList(oldList, products, sameItem = { a, b -> a.id == b.id }).dispatchUpdatesTo(this)
}
于 2022-02-11T09:54:23.670 回答
-1

检查布局管理器是否已经设置并获取当前滚动位置。像这样:

var itemPostion= 0
if(myRecyclerView.layoutmanager != null){
  itemPostion = (myRecyclerView.layoutmanager as LinearLayoutManager)
.findFirstCompletelyVisibleItemPosition()
}

您可以在GitHub 上查看此示例项目

于 2020-02-20T06:41:05.223 回答