在顶部添加新项后,Recycler视图未滚动到顶部,因为尚未对列表适配器进行更改

nay*_*rde 2 android kotlin android-recyclerview android-architecture-components

我在实时数据的开头获取了包含新项的新列表,然后使用其数据更新适配器

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
        recyclerView.scrollToPosition(0)
}
Run Code Online (Sandbox Code Playgroud)

The*_*eme 11

submitList它是在后台线程上工作的,所以总会存在无法解决延迟的竞争条件。幸运的是,RecyclerView.AdapterDataObserver当列表计算完成时,我们可以使用回调来通知:

yourRecyclerViewAdapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() {
    override fun onChanged() {
        recycler_view_list.scrollToPosition(0)
    }
    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        recycler_view_list.scrollToPosition(0)
    }
    override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
        recycler_view_list.scrollToPosition(0)
    }
    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        recycler_view_list.scrollToPosition(0)
    }
    override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
        recycler_view_list.scrollToPosition(0)
    }
    override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
        recycler_view_list.scrollToPosition(0)
    }
})

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案,谢谢!但我必须跳过“onItemRangeInserted()”的第一次调用,以避免在旋转时丢失滚动位置。 (2认同)

RKS*_*RKS 5

使用这种方式

viewModel.myLiveData.observe { this, Observer { myList -> 
    adapter.submitList(myList) // Assuming you are notifying adapter by notifydatasetchanged()
    recyclerView.post { recyclerView.scrollToPosition(0) }
}
Run Code Online (Sandbox Code Playgroud)

这里post给 UI 线程一些时间来用新数据填充 Recycler,然后调用scrollToPosition.

  • _some time_ -> 该帖子告诉 android,将此工作添加到 UI 线程工作队列中。这并不是“给它一些时间”,这只是您将工作发布到已经在做的事情的列表上的副作用。这就是为什么它可能像这样工作,但要小心,如果数据很长或者提交列表的 diff util 需要更长的时间,这不会总是按照您的预期运行。 (9认同)