1

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.

Tartar
  • 5,149
  • 16
  • 63
  • 104
  • Are you sure that all the results are being observed in the viewModel. What I mean is it could be possible that results are coming fast. LiveData being an Observable ViewHolder will simply pass the latest value. Try to create a container to record all the values that are coming from your Observable. – Karan Dhillon Apr 23 '20 at 19:25
  • This to me looks like the case where you are treating LiveData as an Observable. – Karan Dhillon Apr 23 '20 at 19:28
  • I just need to pass the result to view via the LiveData field. Each result corresponds to a set of data that will be set in a Recyclerview row. – Tartar Apr 23 '20 at 19:33
  • https://chat.stackoverflow.com/rooms/212382/discussion-on-livedata Please join the chat so i can understand more. Thanks – Karan Dhillon Apr 23 '20 at 19:38
  • Did you really name both your `LiveData` and `MutableLiveData` `_data`, or is that a typo? And is `_data.post` supposed to be `_data.postValue`? – Michael Apr 23 '20 at 19:42
  • The documentation for `postValue` says that: _"Posts a task to a main thread to set the given value. If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched"_ – Michael Apr 23 '20 at 19:42
  • _ notation is common when using LiveData. The one with _ is mutable and should only be used in the scope in which it is defined. Exposing it should be done by assigning it to another variable whose type is LiveData, to restrict observers changing the value of livedata. – Karan Dhillon Apr 24 '20 at 01:54
  • @Michael it is a typo. – Tartar Apr 24 '20 at 07:21
  • Hi did you find any solution on this? Facing same issue – amodkanthe Dec 15 '22 at 15:16

1 Answers1

2

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.

Karan Dhillon
  • 1,186
  • 1
  • 6
  • 14