实时数据观察者被多次调用

时间:2020-12-19 12:51:42

标签: android android-livedata

我有一个 Android 应用程序,当用户执行某些操作(例如删除帖子)时,它会显示吐司,吐司会出现并显示“已删除帖子”,但是如果我们将 Android 手机置于水平位置,吐司会一次又一次地出现,永远不会停止. 我怎样才能让吐司停止?

        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") }
            }
        })
    } ``` 

3 个答案:

答案 0 :(得分:2)

LiveData 不是为单个事件设计的。

Medium Blog

使用 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
}

简单的样品使用

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

活动

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

使用 Event 将相关部分包装在您的代码中。

答案 1 :(得分:0)

您可以在观察到状态 livedata 后将其设置为 null,如果您的 livedata 为 null,则在观察者内部检查是否为 null,然后返回

答案 2 :(得分:0)

LiveData 本质上是粘性的,这意味着只要您的片段或活动变得活跃,它就会收到最后一个值。因此,它不适用于 1 次事件,例如显示吐司/对话框/小吃店。

您可以像这样使用 SingleLiveEvent:How to use Single Live Event to show toast in Kotlin

更详细的文章:https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150