Android 在顶部添加新项目后,回收器视图不会滚动到顶部,因为列表适配器尚未发生更改

Android 在顶部添加新项目后,回收器视图不会滚动到顶部,因为列表适配器尚未发生更改,android,android-recyclerview,kotlin,android-architecture-components,Android,Android Recyclerview,Kotlin,Android Architecture Components,我将在live data中获取一个新列表,该列表的开头有一个新项目,然后使用它的数据更新适配器 viewModel.myLiveData.observe { this, Observer { myList -> adapter.submitList(myList) recyclerView.scrollToPosition(0) } 解决此问题的另一种方法是将Recyclerview包装在嵌套的ScrollView中 <android.supp

我将在live data中获取一个新列表,该列表的开头有一个新项目,然后使用它的数据更新适配器

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
        recyclerView.scrollToPosition(0)
}

解决此问题的另一种方法是将Recyclerview包装在嵌套的ScrollView中

 <android.support.v4.widget.NestedScrollView
    android:id="@+id/nsv_data"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
           <android.support.v7.widget.RecyclerView
                android:id="@+id/rv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:nestedScrollingEnabled="false"
                tools:listitem="@layout/rv_interview_prep_row"
                android:visibility="gone"
                android:background="@color/white" />
</android.support.v4.widget.NestedScrollView>
你也可以使用

recyclerView.smoothScrollToPosition(0);

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
         recyclerView.smoothScrollToPosition(0);
}

谢谢大家的回复。但对我来说唯一有效的工作是在执行submitList后延迟1秒。尽管不合适,但其工作原理如下:

adapter.submitList()
将始终使用相同的执行时间(毫秒内)

我刚打过电话

Handler().postDelayed ({
  recycler.scrollToPosition(0)
}, 1000)
这样

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

这里的
post
给了UI线程一些时间来用新数据填充回收器,然后调用
scrollToPosition
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) 
}

与一秒钟的延迟recyclerView.post{recyclerView.scrollToPosition(0)}相比,这会更好。你可以试试这个。此外,这不会在每次数据更新时创建Handler()。它将队列滚动任务到更新时使用的同一队列RecyclerView。检查我的答案,这样你将节省少量内存(保存创建的每个处理程序)和计算(创建处理程序对象)并且在滚动时几乎没有可见的延迟。如果有帮助,请不要忘记接受并更新答案。某个时间->帖子告诉android,将此工作添加到UI线程工作队列。这并不是“给它一些时间”,这只是你将工作发布到已经在做事情的列表上的副作用。这就是为什么它可能是这样工作的,但是要小心,如果数据很长或者提交列表的diff-util需要更长的时间,这不会总是像您所期望的那样。在嵌套的滚动视图中包装RecyclerView几乎总是一个坏主意。例如,一个不太为人所知的副作用是,recyclerview不能再“循环”视图,因为它不知道可用空间的高度(嵌套的滚动视图必须膨胀所有视图以确定内容的“高度”)。用100行试试这个:没问题。现在用1000试试很好的解决方案,谢谢!但是我必须跳过第一次调用
onItemRangeInserted()
,以避免在旋转时丢失滚动位置。
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) 
}