嵌套recyclerView动态数据一致性

Nested recyclerView dynamic data consistency

我有垂直的 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)
    }
    ...
}

我有这个问题,因为每个嵌套列表都创建了几个 ViewHolder。在调用 notifyItemChanged() 的地方(第 diff.dispatchUpdatesTo(this) 行),recyclerView 获取缓存的 viewHolder,为他调用 bind 并替换已经附加的 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)
        }
    }