简体   繁体   中英

Live data observer getting called multiple times

I have an Android app that shows a toast when user perform some actions like post deletion for example , a toast appears and says "post deleted" but if we turn the android phone on the horizontal the toast appears again and again never stop. how can i make the toast stop?

        postsViewModel.genericResponseLiveData.observe(this, Observer {
            when (it.status) {
                Status.LOADING -> { Timber.e("Loading...") }

                Status.SUCCESS -> {
                    when (it.item) {
                        GenericResponse.ITEM_RESPONSE.REPORT_POST -> toast("Post reported \uD83D\uDC4A")
                        else -> Timber.e("Success \uD83D\uDE03")
                    }
                }

                Status.ERROR -> { toast("${it.error}. Please try again") }
            }
        })
    } ``` 

LiveData is not designed for single events.

Medium Blog

Using Event

/**
 * 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
}

Easy Sample Usage

class ListViewModel : ViewModel {
    private val _navigateToDetails = MutableLiveData<Event<String>>()

    val navigateToDetails : LiveData<Event<String>>
        get() = _navigateToDetails


    fun userClicksOnButton(itemId: String) {
        _navigateToDetails.value = Event(itemId)  // Trigger the event by setting a new Event as a new value
    }
}

Activity

myViewModel.navigateToDetails.observe(this, Observer {
    it.getContentIfNotHandled()?.let { // Only proceed if the event has never been handled
        startActivity(DetailsActivity...)
    }
})

Wrap the relevant section in your code with Event.

您可以在观察它后将 Status livedata 设为 null,如果您的 livedata 为 null,则在观察者内部检查 null 然后返回

LiveData is sticky in nature which means whenever your fragment or activity becomes active it will receive the last value. So it's not good for 1 time event like showing a toast/dialog/snackbar.

You can use SingleLiveEvent like this: How to use Single Live Event to show toast in Kotlin

More detailed Article on this: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM