如何在 jetpack-navigation 中保存状态列表
how to save state list in jetpack-navigation
我使用 jetpack-navigation 设计了一个应用程序
当我从一个片段移动到另一个片段时,出现如下图所示的问题,列表的状态消失了。
实际上,当从布局返回时,文章会在堆栈中重新创建,列表状态不会被保存,用户将不得不再次滚动。请帮帮我?
jetpack-navigation
每次导航操作都会重新创建片段。您可以将滚动位置存储在 activity 中并从那里加载它。但是这样做,滚动位置将在 activity 重新创建(例如旋转设备)时丢失。
更好的方法是将其存储在 ViewModel 中。 (参见 https://developer.android.com/topic/libraries/architecture/viewmodel)
视图模型在 activity 重新创建后仍然存在,您可以存储滚动位置。
然后你可以加载这个位置并告诉列表滚动到这个位置(例如,对于带有 LinearLayoutManager 的 RecyclerView,通过调用 scrollToPositionWithOffset(...))
我每 15 秒重新加载一次 recyclerView 数据。为了在应用程序之间切换时保持滚动位置,我在相应的片段覆盖方法中使用了 onSaveInstanceState() 和 onRestoreInstanceState(mRVState) 方法。但是当我想在不同片段之间切换时保存位置,我想出了这个解决方案:
1.Set RecyclerView.OnScrollListener() 在 Fragment 的 onResume() 方法中获取当前第一个可见项每个卷轴上的位置。如您所见,位置变量位于父级 activity 中,因此它不会在片段替换时丢失:
override fun onResume() {
super.onResume()
if (updateListRunnable != null) setAndRunUpdateListRunnable()
mRV?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
mainActivity.lastRVPosition =
(recyclerView.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
}
})
}
2.Use scrollToPosition() adapter 内部数据被替换后recyclerView 的方法:
private fun setDataList(dataList: List<Data?>?) {
val mutableDataList = dataList?.toMutableList()
val currentItemCount = binding?.rvDataList?.adapter?.itemCount
if (currentItemCount == null || currentItemCount == 0) {
// create new adapter with initial data
val adapter = DataListAdapter(mutableDataList, baseVM, mainVM)
binding?.rvDataList?.adapter = adapter
binding?.rvDataList?.layoutManager = LinearLayoutManager(context)
mRV?.scrollToPosition(mainActivity.lastRVPosition);
} else {
// update existing adapter with updated data
mRVState = mRV?.layoutManager?.onSaveInstanceState()
val currentAdapter = binding?.rvDataList?.adapter as? DataListAdapter
currentAdapter?.updateDataList(dataList)
currentAdapter?.notifyDataSetChanged()
mRV?.layoutManager?.onRestoreInstanceState(mRVState)
mRV?.scrollToPosition(mainActivity.lastRVPosition);
}
}
如你所见,我也使用onSaveInstanceState()/onRestoreInstanceState() before/after替换数据,这样如果在数据替换之前没有滚动,位置仍然会被保存。滚动侦听器保存的位置仅在片段之间切换时有用。
我使用 jetpack-navigation 设计了一个应用程序 当我从一个片段移动到另一个片段时,出现如下图所示的问题,列表的状态消失了。
实际上,当从布局返回时,文章会在堆栈中重新创建,列表状态不会被保存,用户将不得不再次滚动。请帮帮我?
jetpack-navigation
每次导航操作都会重新创建片段。您可以将滚动位置存储在 activity 中并从那里加载它。但是这样做,滚动位置将在 activity 重新创建(例如旋转设备)时丢失。
更好的方法是将其存储在 ViewModel 中。 (参见 https://developer.android.com/topic/libraries/architecture/viewmodel)
视图模型在 activity 重新创建后仍然存在,您可以存储滚动位置。
然后你可以加载这个位置并告诉列表滚动到这个位置(例如,对于带有 LinearLayoutManager 的 RecyclerView,通过调用 scrollToPositionWithOffset(...))
我每 15 秒重新加载一次 recyclerView 数据。为了在应用程序之间切换时保持滚动位置,我在相应的片段覆盖方法中使用了 onSaveInstanceState() 和 onRestoreInstanceState(mRVState) 方法。但是当我想在不同片段之间切换时保存位置,我想出了这个解决方案:
1.Set RecyclerView.OnScrollListener() 在 Fragment 的 onResume() 方法中获取当前第一个可见项每个卷轴上的位置。如您所见,位置变量位于父级 activity 中,因此它不会在片段替换时丢失:
override fun onResume() {
super.onResume()
if (updateListRunnable != null) setAndRunUpdateListRunnable()
mRV?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
mainActivity.lastRVPosition =
(recyclerView.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
}
})
}
2.Use scrollToPosition() adapter 内部数据被替换后recyclerView 的方法:
private fun setDataList(dataList: List<Data?>?) {
val mutableDataList = dataList?.toMutableList()
val currentItemCount = binding?.rvDataList?.adapter?.itemCount
if (currentItemCount == null || currentItemCount == 0) {
// create new adapter with initial data
val adapter = DataListAdapter(mutableDataList, baseVM, mainVM)
binding?.rvDataList?.adapter = adapter
binding?.rvDataList?.layoutManager = LinearLayoutManager(context)
mRV?.scrollToPosition(mainActivity.lastRVPosition);
} else {
// update existing adapter with updated data
mRVState = mRV?.layoutManager?.onSaveInstanceState()
val currentAdapter = binding?.rvDataList?.adapter as? DataListAdapter
currentAdapter?.updateDataList(dataList)
currentAdapter?.notifyDataSetChanged()
mRV?.layoutManager?.onRestoreInstanceState(mRVState)
mRV?.scrollToPosition(mainActivity.lastRVPosition);
}
}
如你所见,我也使用onSaveInstanceState()/onRestoreInstanceState() before/after替换数据,这样如果在数据替换之前没有滚动,位置仍然会被保存。滚动侦听器保存的位置仅在片段之间切换时有用。