我在应用程序中聊天,我希望当新消息到来且第一个可见项的位置为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什么时候完成的吗?
答案 0 :(得分:1)
您可以使用RecyclerView.AdapterDataObserver()并处理所需的内容。
创建实现RecyclerView.AdapterDataObserver()的侦听器类
并在您的适配器构造函数中调用registerAdapterDataObserver(您的监听器)
然后处理您的回调。