using PagedList, and here it does not have database back, but a data list (call it CachedDataList
) in the memory which could be filled in by fetchMore()
function.
Having the PositionalDataSource
, DataSource.Factory
and PagedList.BoundaryCallback
, it works but one issue here.
The flow is the PositionalDataSource's loadInitial()
will be called at beginning to start to load data from the CachedDataList
, and call loadRange()
after that to continue loading data from the CachedDataList
by page size.
When all data from the CachedDataList
are paged off, the BoundaryCallback::onItemAtEndLoaded()
will be called (if there is no backing data at beginning then the BoundaryCallback::onZeroItemsLoaded()
is called),
In there it will start to asking fetchMore to append more data into the CachedDataList
, and when the new data is appended to it then call the DataSource's invalidate()
to restart the new PagedList and DataSource pair, and starting from PositionalDataSource's loadInitial()
again.
It is done by
observableCachedData.observe(owner, refreshHandler!!)
//??? TODO: how to only listen to newly posted data after
//starting the observe?
//DOC: 'If LiveData already has data set, it will be delivered to the observer.'
// fetchMore
val didFetch = dataRequester.fetchMore() //asyc call
here, it observes the observableCachedData's change, and if there is change then the onChanged()
of the
class RefreshHandler(val observableCachedData: MutableLiveData<List<Data>>) : Observer<List<Data>> {
override fun onChanged(datalist: List<Data>?)
will be called, and in which to call the DataSource's invalidate()
but the subscription of observableCachedData.observe()
causes the refreshHandler
called immediately (it's by design as stated in the DOC), this behavior is not desired here since we want the handler is called when the new data is append to the CachedDataList
.
i.e. the CachedDataList
had 30 data, when do fetchMore() there will be another 30 data appended to it, become 60. But this onChange()
is called with data still at 30 (the append has not been coming yet).
Is there a way to subscribe to a live data but only get notified for update that happened after it is subscribed to it?
class DataBoundaryCallback(
private val owner: LifecycleOwner,
private val dataRequester: FetchMoreRequester,
private val dataSourceFactory: DataSourceFactory?
) : PagedList.BoundaryCallback<IData>() {
private var hasRequestInProgress = false
override fun onZeroItemsLoaded() {
requestAndSaveData()
}
override fun onItemAtEndLoaded(itemAtEnd: IData) {
requestAndSaveData()
}
private fun requestAndSaveData() {
if (hasRequestInProgress) return
hasRequestInProgress = true
// ask dataRequester to fetchMore
// setup observer
val cachedDataList = dataRequester.getCachedLiveData()
val observableCachedData = cachedDataList.getLiveData()
refreshHandler = RefreshHandler(observableCachedData)
observableCachedData.observe(owner, refreshHandler!!) //??? TODO: how to only listen to newly posted data after starting the observe? DOC: 'If LiveData already has data set, it will be delivered to the observer.'
// fetchMore
val didFetch = dataRequester.fetchMore()
if (!didFetch) { //not stated fetch
hasRequestInProgress = false
observableCachedData.removeObserver(refreshHandler!!)
}
}
var refreshHandler : RefreshHandler? = null
inner class RefreshHandler(val observableCachedData: MutableLiveData<List<Data>>) : Observer<List<Data>> {
override fun onChanged(datalist: List<Data>?) {
observableCachedData.removeObserver(refreshHandler!!)
val dataSource = dataSourceFactory.getPositionalDataSource()
// to start a new PagedList and DataSource pair flow
// and trigger the DataSource's loadInitial()
dataSource.invalidate()
}
}
}