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

标签 android kotlin android-recyclerview listadapter

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

我的适配器是从 RecyclerView.Adapter<RecyclerView.ViewHolder> 扩展而来的并且我找到了一个小的 hacky 解决方案来让它工作:

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 何时完成所有操作?

最佳答案

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

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

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

然后处理您的回调。

参见 RecyclerView.AdapterDataObserver

关于android - RecyclerView - 在 notifiyItemInserted(0) 之后保持在 0 位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54347878/

相关文章:

android - 如何将 ITelephony.aidl 添加到 Eclipse?

android - 如何从 avd 设备中删除离线模拟器?

java - 有人可以修复我的 CalledFromWrongThreadException 吗?

hibernate - Kotlin Hibernate JPA Lazy提取无法通过 Controller 工作

android - FragmentTransaction 隐藏/显示有时不起作用

android - 如何为多选列表首选项实现 'Select all' 选项?

android-studio - 如何防止在我的对象上使用 kotlin 扩展?

java - 无法在屏幕旋转时保持 RecyclerView 位置

android - 分隔线未显示在回收站 View 项目中

java - 回收者认为适配器没有被调用