嵌套的recyclerView动态数据一致性

时间:2019-07-19 07:24:23

标签: android android-recyclerview android-adapter nested-lists android-diffutils

我有几个嵌套的水平recyclerView的垂直recyclerView。每个嵌套列表都通过DiffUtils机制动态更新。

当我更新嵌套列表时,我等待滚动保持在相同位置,并且新项目出现在它的右侧,但是滚动在页面上移到了前面。发生了什么事?

class Adapter : RecyclerView.Adapter {
    private var nestedItems: List<Item> = emptyList()
    fun updateNestedList(items: List<Item>) {
        val diff = DiffUtil.calculateDiff(...)
        nestedItems = items
        diff.dispatchUpdatesTo(this)
    }
    override fun onCreateViewHolder() {
        when (itemType) {
            ...
            ITEM_TYPE_HORIZONTAL -> NestedListViewHolder()
        }
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            ...
            is NestedListViewHolder -> (holder as NestedListViewHolder).bind(items)
        }
    }
}

class NestedListViewHolder : RecyclerView.ViewHolder {
    private val adapter by lazy {
        NestedAdapter().apply {
            val layoutManager = LinearLayoutManager(containerView.context, LinearLayoutManager.HORIZONTAL, reverseLayout = false)
            contacts_list.layoutManager = layoutManager
            contacts_list.isNestedScrollingEnabled = false
            contacts_list.adapter = this
        }
    }
    fun bind(items: List<Item>) {
        adapter.updateContacts(items)
    }
}

class NestedAdapter : RecyclerView.Adapter {
    private var items: List<Item> = emptyList()
    fun updateItems(_items: List<Item>) {
        val diff = DiffUtil.calculateDiff(...)
        items = _items
        diff.dispatchUpdatesTo(this)
    }
    ...
}

1 个答案:

答案 0 :(得分:0)

我有这个问题,因为对于每个嵌套列表,很少创建ViewHolders。在notifyItemChanged()称为(第diff.dispatchUpdatesTo(this)行)的情况下,recyclerView获取缓存的viewHolder,为其调用绑定并替换已经连接的viewHolder。 https://android.jlelse.eu/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91#.dcsykhoh9

为解决此问题,我允许recyclerView重用NestedListViewHolder。

    contacts_list.itemAnimator = object : DefaultItemAnimator() {
        override fun canReuseUpdatedViewHolder(viewHolder: RecyclerView.ViewHolder, payloads: MutableList<Any>): Boolean {
            return viewHolder is NestedListViewHolder || super.canReuseUpdatedViewHolder(viewHolder, payloads)
        }
    }