How to Observe Event Only Once Using SingleLiveEvent in Android? - GeeksforGeeks

08 Sep, 2021
Have you ever had to deal with a Dialog or a SnackBar that, after being triggered/shown or dismissed, gets triggered/shown again after a device rotation? This is most likely connected to the use of LiveData observables to communicate between the ViewModel and the Activity/Fragment.
Using LiveData objects for events might be viewed as a poor design choice, especially when the event is only required once. We can use some boolean flags to assist the view in determining if the Dialog/SnackBar should be triggered/shown or not. However, this might result in a solution that is difficult to comprehend and maintain, as well as being unattractive. As you can see it has the type of live data, the data is consumed continuously, but we only want to get it once.
There are no memory leaks:
Observers are tied to Lifecycle objects and clean up after themselves when the lifecycle with which they are connected is destroyed.
There have been no accidents as a result of activity being halted:
If the observer’s lifetime is idle, like in the case of a back stack activity, it does not receive any LiveData events. LiveData just follows the observer design, and I don’t believe the above-mentioned use case warrants its own variant of the observable class. So, how can we resolve the dialogue issue? Rather than altering the behavior of LiveData, we should keep to the basics of the MVVM paradigm and, if necessary, have the ViewModel tell the ViewModel about the dismissed dialogue. Following that, the VM might reset or alter the status of the event. I realize it’s easy to forget to alert ViewModel, and we’re increasing View’s responsibilities. But, after all, it is the View’s job: to inform the VM of any user action.
Create an ‘Event’ class that is general (maybe call it LiveEvent). Give it observe(owner, observer) and observeForever functions (observer). Give it the same contract and functionality as LiveData. Except that, instead of a persistent value, the LiveEvent just notifies active observers while sending along with the data.
Kotlin
class LiveEvent<C> {...  fun sendingValue(data: C) {    observers.forEach { gfg ->      if (gfg.isActive()) gfg.onChanged(data)    }  }}
Put the LiveEvent in your basic ViewModel class if you want to utilize it for publishing notifications, SnackBars, or anything on many screens. Then, after initializing the ViewModel in your basic Fragment class, watch for that LiveEvent.
Kotlin
abstract class GeeksforGeeksViewModel : ViewModel() {  protected val fireAlertedEvent = LiveEvent<FireAlert>()}abstract class BaseFragment : Fragment() {  fun onViewModelInitialized() {    viewModel.fireAlertedEvent.observe(this, { fireAlert ->      fireAlert.show()    }  }}class GeeksforGeeksSample : GeeksforGeeksViewModel() {  fun onSaveSuccess() {    fireAlertedEvent.postValue(FireAlert("yay! we got your stuff!"))  }}
The optimum solution would be an event source with automatic unsubscription on destruct that enqueues events as long as no watchers are present and then sends all events to the first observer that subscribes. That can handle the events in whatever way it deems fit. When you need to manage flow, using a callback with distinct success/failure methods is a terrible idea. Make use of an ADT (sealed class).
Blogathon-2021
Picked
Android
Blogathon
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Flutter - Custom Bottom Navigation Bar
How to Read Data from SQLite Database in Android?
Android Listview in Java with Example
How to Post Data to API using Retrofit in Android?
Retrofit with Kotlin Coroutine in Android
How to Call or Consume External API in Spring Boot?
Re-rendering Components in ReactJS
SQL Query to Insert Multiple Rows
Python NOT EQUAL operator
Difference Between Local Storage, Session Storage And Cookies