PagedListAdapter重新加载没有占位符的数据

时间:2019-05-31 15:40:45

标签: android paging android-jetpack android-jetpack-paging

我正在使用PagedListAdapter,并且必须在恢复屏幕时重新加载数据。
对于这种情况,我不想在加载数据时清除适配器并将其显示为空或占位符。
我想显示以前的数据,并在收到新数据后立即使用diff更新。
但是现在,当我执行dataSource.invalidate()时,它将立即提交一个空列表,这将导致清除适配器并显示占位符。

现在我的代码如下:

class PortfolioListDataSource(
        private val viewModel: PortfolioViewModel,
        private val tabType: PortfolioTabType
) : PageKeyedDataSource<Int, Investment>() {

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Investment>) {
        val offset = 0
        viewModel.loadInvestments(tabType, offset, Consumer {
            val nextKey = if (it.data.size < params.requestedLoadSize) null else it.data.size
            callback.onResult(it.data, offset, it.total, null, nextKey)
        })
    }

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Investment>) {
        val offset = params.key
        viewModel.loadInvestments(tabType, offset, Consumer {
            val nextKey = offset + it.data.size
            callback.onResult(it.data, nextKey)
        })
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Investment>) {

    }

    class Factory(
            val viewModel: PortfolioViewModel,
            private val tabType: PortfolioTabType
    ) : DataSource.Factory<Int, Investment>() {

        val sourceLiveData = MutableLiveData<PortfolioListDataSource>()

        override fun create() = PortfolioListDataSource(viewModel, tabType)
                .also { sourceLiveData.postValue(it) }
    }
}

在这里我初始化

val pagedListConfig = PagedList.Config.Builder()
            .setInitialLoadSizeHint(20)
            .setPageSize(20)
            .build()

ordersLiveData = LivePagedListBuilder(factory, pagedListConfig).build()

在这里填充适配器

viewModel.ordersLiveData.observe(this, Observer {
    adapter.submitList(it)
})

并用

刷新
// TODO Here I want to fetch new data, but not invalidate current dataset while it is loading
factory.sourceLiveData.value?.invalidate()

我不知道该怎么做

1 个答案:

答案 0 :(得分:1)

是的,invalidate()将清除当前数据集。 因此,您将进入“正在加载/占位符”状态。 也无法更新特定页面。 假设您位于第5页,并且想要更新该特定页中的数据。如果不调用invalidate(),这也是不可能的,这将清除数据集并将带到Recyclerview到第一页(列表顶部)。

摆脱所有这些问题的唯一方法是在Room中引入一个持久层。 https://github.com/googlesamples/android-architecture-components/tree/master/PagingWithNetworkSample#paging-with-database-and-network

根据此处的文档: https://developer.android.com/reference/androidx/paging/DataSource#updating-paged-data

  

如果您有更精细的更新信号,例如网络API   表示要更新列表中的单个项目,建议   将数据从网络加载到内存中。然后将该数据呈现给   通过包装内存中快照的数据源的PagedList。每一次   内存中的副本更改,使先前的数据源无效,并且   可以创建包含快照新状态的新快照。

https://developer.android.com/topic/libraries/architecture/paging/data#consider-content-updates

  

在构造可观察的PagedList对象时,请考虑内容如何   更新工作。如果您是直接从Room数据库加载数据   更新会自动推送到您应用的用户界面。

在这种情况下,您始终可以在恢复屏幕时从DB加载数据,直到从您的API获取数据为止。