Android SingleLiveEvent (of LiveData) for UI Event

SingleLiveEvent:-

SingleLiveEvent is a subclass of MutableLiveData with a single Observer Observing it at a time, hence it is aware of view’s lifecycle.

The problem

The problem is started since LiveData promises some advantages where you can find them in its . I list them here by the way:

Ensures your UI matches your data state LiveData follows the observer pattern. LiveData notifies objects when the lifecycle state changes. You can consolidate your code to update the UI in these Observer objects. Instead of updating the UI every time the app data changes, your observer can update the UI every time there's a change.

No memory leaks Observers are bound to objects and clean up after themselves when their associated lifecycle is destroyed.

No crashes due to stopped activities If the observer’s lifecycle is inactive, such as in the case of an activity in the back stack, then it doesn’t receive any LiveData events.

No more manual lifecycle handling UI components just observe relevant data and don’t stop or resume observation. LiveData automatically manages all of this since it’s aware of the relevant lifecycle status changes while observing.

Always up to date data If a lifecycle becomes inactive, it receives the latest data upon becoming active again. For example, an activity that was in the background receives the latest data right after it returns to the foreground.

Proper configuration changes If an activity or fragment is recreated due to a configuration change, like device rotation, it immediately receives the latest available data.

Sharing resources You can extend a object using the singleton pattern to wrap system services so that they can be shared in your app. The LiveData object connects to the system service once, and then any observer that needs the resource can just watch the LiveData object. For more information.

But some of these advantages cannot be useful in all scenarios and there is no way to disable them when you instantiate a LiveData. For instance, the property of “always up to date data” cannot be disabled and the main problem which this article wants to tackle is a way to disabling it.

However, I have to thank Google for the “proper configuration changes” property, which is so so useful. But still, we need to be able to disable it when we want. I have no scenario where I need to disable it but please let people choose.

Why use SingleLiveEvent:-

So, What is the Solution here?

For these types of tasks, class came for the rescue. It is nothing but an extension of the MutableLiveData class but it emits the data only once whenever required.

We need to create a class file called SingleLiveEvent in our project and the SingleLiveEvent class looks like,

class SingleLiveEvent<T> : MutableLiveData<T>() {    private val mPending = AtomicBoolean(false)    @MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<T>) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
}
// Observe the internal MutableLiveData
super.observe(owner, object : Observer<T> {
override fun onChanged(t: T?) {
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t)
}
}
})
}
@MainThread
override fun setValue(t: T?) {
mPending.set(true)
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/

@MainThread
fun call() {
setValue(null)
}
companion object { private val TAG = "SingleLiveEvent"
}
}

and to use it in ViewModel you just need to use it similarly how we use LiveData,

private val uploadData = SingleLiveEvent<String>()
fun getUploadData(): SingleLiveEvent<String> {
return uploadData
}

and in the Activity/Fragment file, we will use similarly how we used in the above code,

viewModel.getUploadData().observe(this, Observer {
//Snackbar
})

The above code will only emit the data only once whenever it is required and then will stop observing.

To read more about Event Observer, We will discuss in part-2… or until you can read from below link-

Thanks for reading…

Senior Software Engineer | Android | Java | Kotlin|Xamarin Native Android|Flutter