14

我一直在尝试PagedListAdapter但无法弄清楚如何正确恢复适配器位置。

最后一次尝试是lastKey从当前列表中保存。

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)

    val lastKey = adapter.currentList?.lastKey as Int

    outState.putInt("lastKey", lastKey)
}

但是当恢复我的适配器并传递lastKeyPagedListBuilder我上次看到的内容和显示的内容时,会有很大的不同。

    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"))

惨败。欢迎任何建议:)

4

1 回答 1

12

终于设法让它工作了。

前提条件 - 您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)
}

哦,当绑定时,如果 item 为空ViewHolderonBindViewHolder我会快速退出。

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val item = getItem(position) ?: return
    ... 
}

因为它将为空,否则适配器项目计数将与保存的状态项目计数不匹配(在这里猜测),这就是为什么在我的一些实验中,布局在第 2 页上跳动,而它在第 1 页上工作。

如果有更好的方法可以在不手动存储然后使用的情况下解决这个问题lastLayoutManagerState- 请告诉我。

于 2018-08-07T19:40:32.747 回答