how to observe a liveData only for the new update after the subscription to the liveData
Asked Answered
G

2

7

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()
        }
    }
}
Gamb answered 22/5, 2018 at 19:59 Comment(0)
L
1

You can use SingleLiveEvent

SingleLiveEvent

Lammastide answered 22/5, 2018 at 20:45 Comment(1)
Tried using this.No use foundValvule
G
0

made it work with checking the emitted data list in the RefreshHandler(val observableCachedData: MutableLiveData<List<Data>>), only invalidate if there is more added to the list.

(it should look for a better way to determine the datalist has truly increased).

inner class RefreshHandler(val observableCachedData: MutableLiveData<List<Data>>) : Observer<List<Data>> {
    val oldData = observableCachedData.value
    override fun onChanged(datalist: List<Data>?) {

        if (datalist.size == oldData.size) {
             // is from previous cached data in the liveData
             return
        }

        observableCachedData.removeObserver(refreshHandler!!)
        val dataSource = dataSourceFactory.getPositionalDataSource()

        // to start a new PagedList and DataSource pair flow
        // and trigger the DataSource's loadInitial()
        dataSource.invalidate()
    }
}
Gamb answered 25/5, 2018 at 13:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.