RecyclerView-在notifiyItemInserted(0)之后保持在0位置

时间:2019-01-24 13:34:07

标签: android kotlin android-recyclerview listadapter

我在应用程序中聊天,我希望当新消息到来且第一个可见项的位置为0时,我的RV保持在位置0,但新消息会添加到当前可见项的上方,但可见项仍位于视图,因此用户必须滚动才能看到新消息。

我的适配器从RecyclerView.Adapter<RecyclerView.ViewHolder>扩展而来,我发现了一个小小的解决方案来使其正常工作:

private suspend fun update(newItems: List<IChatItem>) {
    var recyclerViewState: Parcelable? = null
    if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
        recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
    }

    val diffResult = withContext(Dispatchers.Default) {
        DiffUtil.calculateDiff(Diff(this.currentItems, newItems))
    }

    diffResult.dispatchUpdatesTo(this)

    recyclerViewState?.let {
        recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
    }
}

事情正在保存RV状态,在DiffUtil完成工作后,将其还原。它确实起作用了,但是现在我试图实现新的适配器并从ListAdapter扩展我的适配器类,因为它在另一个线程中启动了DiffUtil。效果很好,但是问题是我不能在这里实现我以前的解决方案,只是不起作用。

我尝试了以下操作:

override fun submitList(list: MutableList<IChatItem>?) {
    var recyclerViewState: Parcelable? = null
    if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
        recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
    }

    super.submitList(list)

    recyclerViewState?.let {
        recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState)
    }
}

但是这不再起作用了。有人有解决方案吗?

PS:我发现了这个问题-Inserting RecyclerView items at zero position - always stay scrolled to top,但我认为这不是在适配器列表中添加空的不可见项的最佳解决方案。还有其他想法吗?

UPD :正如我所想-因为此适配器在另一个线程中启动DiffUtil,所以它在DiffUtil完成其工作之前恢复了RV状态。这段代码有效:

override fun submitList(list: List<IChatItem>?) {
    var recyclerViewState: Parcelable? = null
    if ((recyclerView?.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition() == 0) {
        recyclerViewState = recyclerView?.layoutManager?.onSaveInstanceState()
    }


    super.submitList(list)

    recyclerViewState?.let {
            Handler().postDelayed( 
                { 
                    recyclerView?.layoutManager?.onRestoreInstanceState(recyclerViewState) 
                }, 1000
            )
    }
}

但这不是我想要的。有什么方法可以检测DiffUtil什么时候完成的吗?

1 个答案:

答案 0 :(得分:1)

您可以使用RecyclerView.AdapterDataObserver()并处理所需的内容。

创建实现RecyclerView.AdapterDataObserver()的侦听器类

并在您的适配器构造函数中调用registerAdapterDataObserver(您的监听器)

然后处理您的回调。

请参见RecyclerView.AdapterDataObserver