3

我正在使用 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()

当新数据准备好时,如何保留以前的数据并更新它?

更新:
我想要类似的东西:

if (!refreshing) {
   submitList(it)
}

dataSource.invalidate()我的意思是在调用时不要将空数据集发布到适配器。

我知道上面提到的示例将不起作用,因为一旦提交,数据源会将更新传递给列表的同一实例并且它是完全封装的。
另外,我对数据集本身没有影响。

我尝试使用PagedList.Callback它来知道列表何时更新。但是同样,没有机会以某种方式影响更新行为。

使用常规适配器,在收到新数据之前,我不会设置或更新它的项目。我想在这里实现类似的东西。

4

1 回答 1

1

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

摆脱所有这些问题的唯一方法是在 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 发出对列表中单个项目的更新信号,建议将数据从网络加载到内存中。然后通过包装内存快照的 DataSource 将该数据呈现给 PagedList。每次内存中的副本更改时,都会使先前的 DataSource 失效,并且可以创建一个包装快照新状态的新数据源。

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

在构建可观察的 PagedList 对象时,请考虑内容更新的工作方式。如果您直接从 Room 数据库加载数据,更新会自动推送到您的应用程序的 UI。

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

于 2019-06-08T23:49:22.670 回答