Android: How to Fix a Serious Problem in LiveData
Avoid observing the same data whenever component life-cycle changes
LiveData is from the
JetPack family. It’s mostly used to deliver data from the view model to fragments and activities in the latest architectures, like
LiveData is an observable data holder class. Unlike other data holders,
LiveData is a life cycle aware of respective components like
services, and more. As it is a life cycle aware,
LiveData makes sure that it only publishes the data to those who are observing it when they are active, which means when they’re in the foreground.
LiveData publishes the data to the destination component if it is in the foreground. If it’s not, it might hold the data and deliver it when that specific component comes back to the foreground, like in
Now that we know how it works, let’s say we have a
livedata with multiple observers and three fragments — F1, F2, and F3 — which are in the stack. All three fragments share a
ViewModel and observe a
liveData of type T to show a message.
Now, when we post data of type T through
liveData, because fragment F3 is in the foreground the message is shown first in F3. That’s good — but what happens when we click back? Fragment F2 is resumed, as F2 is one of its subscribers.
LiveData delivers the data again, so the message is shown twice and the same repeats with fragment F1.
This is how
livedata works but, in real-time, there might be cases where once the data is observed, it shouldn’t be observed again. The following section contains the solution.
First, we need to create a class with the name
Event to wrap the data that the
livedata is exposing. Have a look at how to create an
In this class, we maintain a flag
hasBeenHandled to check whether the data is observed at least once.
Now we need to create another class with name
EventObserver that extends
Observer. Just to make the process of using it simple, have a look:
When new data is posted, the
onChanged function is triggered and the flag
hasBeenHandled is set to false. As soon as the first subscriber observed the data, the flag
hasBeenHandled will be true, so that the rest of the subscribers won’t receive the data and the cycle repeats every time new data is posted.
livedata, we need to use
EventObserver instead of regular
Observer so that handling is simplified. Have a look:
This is the solution I’ve found from 2020 AndroidDev summit app source code.
Thank you for reading.