zihadrizkyef
zihadrizkyef

Reputation: 1941

ViewModel observed every back to fragment

I have MainActivity which is containing 5 Fragments (FragmentA, FragmentB, FragmentC....E) with ViewPager. FragmentA has viewModel and observing a MutableLiveData called "showPopupSuccess" which set to true after doing a task.

The problem is when i go to FragmentC and then get back to FragmentA. The popup is showing again because the observer looks like "reactivated". How to get rid of this? I want the mutableLiveData get resetted. So it has no value in it and not showing a popup

This is the video of the bug if you want to see further https://www.youtube.com/watch?v=Ay1IIQgOOtk

Upvotes: 2

Views: 1271

Answers (1)

Ondrej Karmazin
Ondrej Karmazin

Reputation: 508

The easiest way to solve your issue: Use the Event wrapper Instead of "resetting" the LiveData, you can mark its content as handled when you observe it for the first time. Then your repeated observations know it has already been handled and can ignore it.

To create a better answer according to the guidelines I'm copying over the relevant information from the linked article:

The wrapper:

/**
 * Used as a wrapper for data that is exposed via a LiveData that represents an event.
 */
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
}


In the ViewModel:

// Instead of Boolean the type of Event could be popup
// parameters or whatever else.
private val _showSuccess = MutableLiveData<Event<Boolean>>()

val showSuccess : LiveData<Event<Boolean>>
    get() = _showSuccess

In the Fragment:

myViewModel.showSuccess.observe(viewLifecycleOwner, Observer {
    it.getContentIfNotHandled()?.let {
        // This is only executed if the event has never been handled
        showSuccess(...)
    }
})

Upvotes: 5

Related Questions