Search code examples
androidkotlinandroid-livedataandroid-viewmodelmutablelivedata

Some of the multiple concurrent calls to set LiveData are not observed


I have a function to make network calls. It can be called multiple times at the same time and each call runs concurrently.

getDataTask() // it is subscribed on the background thread and observed on the main thread
    .subscribe(
        { result -> onResult(result) },
        { onError() }
    )
    .addToDisposables()

I am able to retrieve the data without any problems. onResult function updates the MutableLiveData field in the ViewModel as

private val _data = MutableLiveData<Data>()
val data: LiveData<Data> get() = _data

private fun onResult(result: Data) = _data.post(result)

And the field is set to be observed in the Fragment's onViewCreated method as

viewModel.data.observe(viewLifecycleOwner, Observer { data -> // DO SOMETHING })

When the back-to-back concurrent calls succeed and try to update the _data field, I noticed that the observer does not observe some of the results. For example, there are 4 concurrent calls start at the same time then they try to post their results and 1 or 2 of the results are not observed. How can I tackle that issue? Any help would be appreciated.


Solution

  • The problem as I believe occurs due to the nature of LiveData. LiveData being an Observable ViewHolder will simply emit only the last value that it processed.

    Now I understand you are doing concurrent calls and there is nothing wrong with that. If you want to save execution time in networking then that is the way to go. However, if you want this concurrency to work with your LiveData instance, and you want your LiveData to emit each and every value it process as soon as a concurrent method successfully returns, then you might be using LiveData wrong.

    What you are seeking is LiveData's Observable nature. You get the lifecycle aware part bundled with it for free, but then again its not your regular Observable, but a special one which only retains the last value.

    In your case, where you want to process each and every value, you are better with using RxJava's Observable. You can make it lifecycle aware as well, by subscribing & unsubscribing in your activity or fragment. You have so many operators in RxJava that one of them will certainly help you, couple that I can think are switchMap and Map.