Reputation: 15046
I am using a PagedListAdapter and have to reload data when the screen is resumed.
For this case, I don't want to clear the adapter and show it empty or placeholders while the data is being loaded.
I want to show the previous data and just update it with the diff once new data is received.
But now when I do dataSource.invalidate()
it immediately submits an empty list which causes clearing the adapter and showing placeholders.
Now my code looks like:
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) }
}
}
Here I initialize the
val pagedListConfig = PagedList.Config.Builder()
.setInitialLoadSizeHint(20)
.setPageSize(20)
.build()
ordersLiveData = LivePagedListBuilder(factory, pagedListConfig).build()
Here I populate the adapter
viewModel.ordersLiveData.observe(this, Observer {
adapter.submitList(it)
})
And refreshing it with
// TODO Here I want to fetch new data, but not invalidate current dataset while it is loading
factory.sourceLiveData.value?.invalidate()
How can I leave the previous data and update it when new data is ready?
Update:
I want something like:
if (!refreshing) {
submitList(it)
}
I mean not to post empty dataset to the adapter when dataSource.invalidate()
is called.
I understand that mention just above sample will not work because once it is submitted, data source passes updates to the same instance of the list and it is fully encapsulated.
Also, I have no effect onto the data set itself.
I tried to use PagedList.Callback
it lets knowing when the list is updated.
But again, there is no chance to somehow affect the update behavior.
With a regular adpter I would just not set or update it's items until new data is received. I want to achieve something similar here.
Upvotes: 4
Views: 2149
Reputation: 3518
Yes, invalidate() will clear the current dataset. So, you will get into a Loading/Placeholder state. It's also not possible to update a specific page. Say, you are on the 5th page and you want to update the data in that specific page. This is also not possible without calling invalidate() which will clear the dataset and will take to Recyclerview to the first page(top of the list).
The only way to get rid of all these issues is to introduce a persistence layer with Room. https://github.com/googlesamples/android-architecture-components/tree/master/PagingWithNetworkSample#paging-with-database-and-network
As per docs here : https://developer.android.com/reference/androidx/paging/DataSource#updating-paged-data
If you have more granular update signals, such as a network API signaling an update to a single item in the list, it's recommended to load data from network into memory. Then present that data to the PagedList via a DataSource that wraps an in-memory snapshot. Each time the in-memory copy changes, invalidate the previous DataSource, and a new one wrapping the new state of the snapshot can be created.
https://developer.android.com/topic/libraries/architecture/paging/data#consider-content-updates
As you construct observable PagedList objects, consider how content updates work. If you're loading data directly from a Room database updates get pushed to your app's UI automatically.
In your case, you can always load the data from the DB when the screen is resumed, until the data from your API gets fetched.
Upvotes: 1