Восстановите позицию PagedListAdapter при возобновлении активности
Я экспериментировал с PagedListAdapter
и не могу понять, как правильно восстановить положение адаптеров.
Последняя попытка была сохранить lastKey
из текущего списка.
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val lastKey = adapter.currentList?.lastKey as Int
outState.putInt("lastKey", lastKey)
}
но при восстановлении моего адаптера и прохождении lastKey
в PagedListBuilder
То, что я видел в последний раз и что отображается, сильно отличается.
val dataSourceFactory = dao.reportsDataSourceFactory()
val builder = RxPagedListBuilder(
dataSourceFactory,
PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setInitialLoadSizeHint(60)
.setPageSize(20)
.setPrefetchDistance(60)
.build()
)
.setInitialLoadKey(initialLoadKey)
.setBoundaryCallback(boundaryCallback)
Если при возобновлении я нахожусь в середине страницы № 4 - адаптер будет в положении в начале страницы № 4. В идеале адаптер должен быть восстановлен в том же положении, что и в последний раз.
Различные попытки сохранить состояние LayoutManager
outState.putParcelable("layout_manager_state", recycler_view.layoutManager.onSaveInstanceState())
а затем восстановить его
recycler_view.layoutManager.onRestoreInstanceState(it.getParcelable("layout_manager_state"))
с треском провалился. Любые предложения приветствуются:)
1 ответ
Наконец-то удалось заставить его работать.
Условие - ваше PagedListAdapter
должен поддерживать нулевые заполнители! setEnablePlaceholders(true)
, Узнайте больше здесь
val dataSourceFactory = dao.reportsDataSourceFactory()
val builder = RxPagedListBuilder(
dataSourceFactory,
PagedList.Config.Builder()
.setEnablePlaceholders(true) //in my original implementation it was false
.setInitialLoadSizeHint(60)
.setPageSize(20)
.setPrefetchDistance(60)
.build()
)
Сохранить состояние как обычно:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val lastKey = adapter.currentList?.lastKey as Int
outState.putInt("lastKey", lastKey)
outState.putParcelable("layout_manager_state", recycler_view.layoutManager.onSaveInstanceState())
}
но при восстановлении - сначала сохраните состояние как переменную и восстановите сохраненное состояние только после отправки списка вPagedListAdapter
private fun showReports(pagedList: PagedList<Report>?) {
adapter.submitList(pagedList)
lastLayoutManagerState?.let {
report_list.layoutManager.onRestoreInstanceState(lastLayoutManagerState)
lastLayoutManagerState = null
}
}
где lastLayoutManagerState
является:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = withViewModel(viewModelFactory) {
observe(reports, ::showReports)
}
report_list.adapter = adapter
lastLayoutManagerState = savedInstanceState?.getParcelable("layout_manager_state")
val lastKey = savedInstanceState?.getInt("lastKey")
viewModel.getReports(lastKey)
}
Ох и когда обязателен ViewHolder
в onBindViewHolder
Я просто выручаю быстро, если элемент нулевой.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = getItem(position) ?: return
...
}
Потому что он будет нулевым, так как в противном случае количество элементов адаптера не будет совпадать с количеством сохраненных элементов состояния (предположим здесь), и именно поэтому в некоторых из моих экспериментов макет прыгал на страницах 2+, пока он работал на странице 1.
Если есть лучшие способы, как подойти к этому без ручного хранения, а затем с помощью lastLayoutManagerState
- дай мне знать.