【问题标题】:Keep previous updated Item in PagedListAdapter after List has been updated from DataSource从 DataSource 更新 List 后,在 PagedListAdapter 中保留先前更新的 Item
【发布时间】:2020-07-15 04:40:49
【问题描述】:

我有一个RecyclerView,它使用一个PagedListAdapter,它从ROOM 和网络API 中获取数据。它使用BoundaryCallback 向API 发出请求,返回的数据被插入到数据库(ROOM)中

我有一个带有递增和递减按钮的列表项...

当前列表是可过滤的,例如我可以按多个类别过滤产品列表

问题

如果我使用增量按钮将产品项目 quantity 增加到例如 12,然后我尝试通过添加更多类别来过滤列表,则当前列表不会刷新,这很好,因为 DiffUtil.ItemCallback 确认项目是相同的,但是一旦我尝试在按更多类别过滤后增加相同产品的数量,它又从零开始......

注意数量不是房间中的一列,它是一个被忽略的变量。

所以我不太确定问题到底出在哪里:下面是执行递增和递减的代码。

override fun onIncrementQuantity(position: Int, item: ProductEntity) {
    item.quantity = item.quantity + 1
    selectedProducts[item.item.id!!] = item
    productAdapter?.notifyItemChanged(position, item)
}
override fun onDecrementQuantity(position: Int, item: ProductEntity) {
    item.quantity = if (item.quantity == 0) 0 else item.quantity - 1
    if (item.quantity == 0) {
        selectedProducts.remove(item.item.id)
    } else {
        selectedProducts[item.item.id!!] = item
    }
    productAdapter?.notifyItemChanged(position, item)
}

【问题讨论】:

    标签: android android-room android-livedata page-library


    【解决方案1】:

    所以经过几个小时的调试,我发现了。

    • 列表最初加载了数据
    • 对当前数据进行更新,例如增量item.quantity = 2
    • 一旦获取新数据(通过搜索或过滤器),如果 itemsAretheSameContentsAreThemSame 则不会调用 onBindViewHolder,因此无需更新视图。此时一切都很好。

    但是,似乎 currentList 已更新为新获取的数据,而不必更新视图...现在,当调用 notifyItemChanged 时,会触发 onBindViewHolder:

    这就是我的onBindViewHolder 的样子

    override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
        getItem(position)?.let { holder.bind(it) }
    }
    

    getItem(position) 为您提供当前列表中已更新且数量恢复为默认值 0 的项目。

    解决方案

    重写RecyclerView.Adapter下面的函数

    override fun onBindViewHolder(
        holder: ViewHolder<ProductEntity>, 
        pos: Int, 
        payloads: MutableList<Any>
    ) { 
        if(payloads.isEmpty()) return super.onBindViewHolder(holder, pos, payloads)
        val product = getItem(pos)?: return
        payloads.forEach {
           val oldProduct = it as ProductEntity
           if(product.item.id == oldProduct.item.id){
              product.quauntity = oldProduct.quantity
           }
        }
    }
    

    有效载荷应包含可用于更新新数据的部分旧数据..

    根据文档

         * The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or
         * {@link #notifyItemRangeChanged(int, int, Object)}.  If the payloads list is not empty,
         * the ViewHolder is currently bound to old data and Adapter may run an efficient partial
         * update using the payload info.  If the payload is empty,  Adapter must run a full bind.
         * Adapter should not assume that the payload passed in notify methods will be received by
         * onBindViewHolder().  For example when the view is not attached to the screen, the
         * payload in notifyItemChange() will be simply dropped.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多