Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop LiveData event being triggered more than Once

I am using MutableLiveData within my application for event based communication. I have single activity two fragments architecture.

With the help of ViewModel, I'm consuming the LiveData events in Fragment-1. But, when I replace this Fragment-1 with Fragment-2 using Menu bar and finally come back to Fragment-1, old values of LiveData are captured again.

How to avoid this problem? Any help/suggestions are highly appreciated! Thank you.

like image 873
Ningan Avatar asked Feb 14 '19 10:02

Ningan


People also ask

Why LiveData Observer is being triggered twice?

The first time it is called upon startup. The second time it is called as soon as Room has loaded the data. Hence, upon the first call the LiveData object is still empty. It is designed this way for good reasons.

Is LiveData lifecycle-aware?

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.

Can LiveData have multiple observers?

SingleLiveEvent has a problem that it's restricted to one observer. I created NEW SingleLiveEvent which can be observed multi observers in a simple way. This is easier than Event which is mentioned in this article. Using this new class is just the same using SingleLiveEvent.


1 Answers

You can use Event to wrap LiveData values to handle consuming its values as in the following article: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

Event class would be like:

open class Event<out T>(private val content: T) {

    var hasBeenHandled = false
        private set // Allow external read but not write

    /**
     * Returns the content and prevents its use again.
     */
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    fun peekContent(): T = content
}

Let us say that your LiveData value is a String then the LiveData of single event would be like:

val navigateToDetails = MutableLiveData<Event<String>>()

like image 157
Metwalli Avatar answered Oct 03 '22 06:10

Metwalli