【问题标题】:how to save state list in jetpack-navigation如何在jetpack-navigation中保存状态列表
【发布时间】:2019-11-04 12:03:46
【问题描述】:

我使用 jetpack-navigation 设计了一个应用程序 如下图所示,当我从一个片段移动到另一个片段时,列表的状态消失了。

事实上,当从一个布局返回时,文章将在堆栈中重新创建,并且列表状态不会被保存,用户将不得不再次滚动。请帮帮我?

jetpack-navigation

【问题讨论】:

  • 您能提供您的 Fragment A 代码吗?

标签: android android-fragments android-jetpack android-viewmodel android-jetpack-navigation


【解决方案1】:

片段会在每次导航操作时重新创建。您可以将滚动位置存储在您的活动中并从那里加载它。但是这样做,滚动位置将在重新创建活动时丢失(例如旋转设备)。

更好的方法是将其存储在 ViewModel 中。 (见https://developer.android.com/topic/libraries/architecture/viewmodel

视图模型在活动重新创建后仍然存在,您可以存储滚动位置。

然后你可以加载这个位置并告诉列表滚动到这个位置(例如,通过调用 scrollToPositionWithOffset(...) 对于带有 LinearLayoutManager 的 RecyclerView)

【讨论】:

  • 感谢您的回答,但是如果加载第 3 页在后面丢失位置,如何在分页列表中存储状态
  • Better approach would be to store it in a ViewModel. 现在如果用户将应用程序置于后台,然后打开相机、谷歌照片,然后将图片分享到 Facebook,然后返回到您的应用程序;你的滚动位置仍然会丢失。这应该通过onSaveInstanceState 保留。更重要的是,通过正确设置视图 ID 和适配器以及布局管理器,滚动位置的恢复实际上应该是自动的,即使在返回导航时也是如此。只有在实际设置前一个数据集之前设置了具有不同项目的不同适配器时,它才会被覆盖。
【解决方案2】:

我每 15 秒重新加载一次 recyclerView 数据。为了在应用程序之间切换时保持滚动位置,我在相应的片段覆盖方法中使用了 onSaveInstanceState() 和 onRestoreInstanceState(mRVState) 方法。但是当我想在不同片段之间切换时保存位置时,我想出了这个解决方案:

1.在Fragment的onResume()方法中设置RecyclerView.OnScrollListener(),获取每个滚动条当前第一个可见item的位置。如您所见,位置变量位于父活动中,因此在片段替换时不会丢失:

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.在adapter内替换数据后,使用recyclerView的scrollToPosition()方法:

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(),这样如果在数据替换之前没有滚动,位置仍然会被保存。滚动监听器保存位置仅在片段之间切换时有用。

【讨论】:

    猜你喜欢
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多