RecyclerView在调用notifyDataSetChanged()后会跳到顶部

3

我有一个包含 swipeRefreshLayout 和无限 recyclerView 的碎片。我的碎片布局代码类似于:

<androidx.constraintlayout.widget.ConstraintLayout
        .
        .
        .
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="true">


    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        .
        .
        .
         android:layout_width="0dp"
         android:layout_height="0dp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="parent" >

        <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_main_news"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

我在onViewCreated()中设置了recyclerView的适配器,并在onResume()中调用notifyDataSetChanged()。在一些设备上,比如三星Galaxy A5,当用户返回到片段并调用notifyDataSetChanged后,recyclerView会移到顶部并显示第一个项目。

我该如何防止这种情况发生? 提前感谢。

更新: 这是我的onResume()代码,它调用了notifyDataSetChanged()

override fun onResume() {
super.onResume()
    if (rv.adapter != null)
        (rv.adapter as MyAdapter).apply {
            fontSize = Options.getFontSize()
            notifyDataSetChanged()
        }
}

你能添加你的 [Java/Kotlin] 代码吗?(在刷新部分) - Ali Sadeghi
请粘贴代码,通知RecyclerView。 - Squti
@Squti,我已经更新了我的问题。 - Mohammad Reza Lohrasbi
2个回答

1
预期的效果是当调用notifyDataSetChanged时,整个视图都会刷新。当你返回到片段时,会调用onResume,接着会调用notifyDataSetChanged。这就是为什么你会看到第一项。
因此,为了防止这种情况发生,你需要在整个数据被更改或需要更新时调用notifyDataSetChanged
我可以提供一些方法。
从onResume中移除notifyDataSetChanged,并使用diffUtil来更新你的recyclerView数据。它只会更新你更改的项目。只有在必要时才更新你的数据,比如如果你在详细信息中更新任何数据并想要在列表中更新,你可以重写onActivityResult并在那里通知你的列表。或者你可以发送广播,在你的列表片段中接收并通知你的列表。
提前感谢,希望这能帮到你。

感谢您的回复。在我的应用程序中,当我们点击列表项时,在详细页面中,我们可以更改应用程序设置,如字体大小。因此,当我们返回到列表时,列表应根据需要进行更新。而且,列表数据不会增加。所以我别无选择,只能调用notifyDataSetChanged()。 - Mohammad Reza Lohrasbi
我认为解决方案是使用diffUtil来处理recyclerView。如果你不了解它,网上有很多资源。请应用它并让我知道更新情况。 - Sayem

-1

当更新时,您可以尝试保存RV的滚动状态:

 val recyclerViewState = rv.layoutManager?.onSaveInstanceState()
 adapter.notifyDataSetChanged()            
 rv?.layoutManager?.onRestoreInstanceState(recyclerViewState)

谢谢回复。我尝试了,但没有效果,RecyclerView 仍然跳到顶部。 - Mohammad Reza Lohrasbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接