首页 > 解决方案 > ViewModel 观察每个返回片段

问题描述

我有 MainActivity,它包含 5 个片段(FragmentA、FragmentB、FragmentC....E)和 ViewPager。FragmentA 具有 viewModel 并观察一个名为“showPopupSuccess”的 MutableLiveData,它在执行任务后设置为 true。

问题是当我去 FragmentC 然后回到 FragmentA。弹出窗口再次显示,因为观察者看起来像“重新激活”。如何摆脱这个?我希望 mutableLiveData 被重置。所以它没有任何价值,也没有显示弹出窗口

如果您想进一步了解,这是该错误的视频 https://www.youtube.com/watch?v=Ay1IIQgOOtk

标签: androidmvvmandroid-viewmodel

解决方案


解决问题的最简单方法:使用Event包装器 而不是“重置” LiveData,您可以将其内容标记handled为第一次观察时的内容。那么你的反复观察就知道它已经被处理过了,可以忽略它。

为了根据指南创建更好的答案,我复制了链接文章中的相关信息:

包装:

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


在视图模型中:

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

在片段中:

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

推荐阅读