如何防止LiveData事件被触发多次

5

我在我的应用程序中使用MutableLiveData进行基于事件的通信。我有单个活动两个片段的架构。

借助ViewModel,在Fragment-1中消耗LiveData事件。但是,当我使用菜单栏将此Fragment-1替换为Fragment-2,并最终返回到Fragment-1时,LiveData的旧值再次被捕获。

如何避免这个问题?非常感谢您提供任何帮助/建议!

谢谢。

5个回答

5
你可以使用 Event 来包装 LiveData 的值,以便像下面这篇文章中所述那样处理其值的消耗: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150 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
}

假设您的LiveData值是一个字符串,那么单次事件的LiveData将会像这样:

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


可以运行了!谢谢 :) - Ningan

1

被接受的答案存在的问题是你只能有一个观察者。这个文章描述了具有多个观察者的解决方案。


0

0

无论您在何处观察liveData,在onChanged方法中通过调用myLiveDataObject.removeObservers(this);来移除观察者。这将在第一次观察数据后移除观察者。


0

简单、清晰、可重用:

class Event<T>(val payload: T, var broadcasted: Boolean = false)

class MutableEventLiveData<T>: MutableLiveData<Event<T>>() {
    fun postEvent(value: T) {
        super.postValue(Event(value))
    }
}

typealias EventLiveData<T> = LiveData<Event<T>>

class EventObserver<T>(private val broadcastCallback: (t: T)->Unit): Observer<Event<T>> {

    override fun onChanged(e: Event<T>) {
        if (!e.broadcasted) {
            broadcastCallback(e.payload)
            e.broadcasted = true
        }
    }
}

示例用法:

class YourViewModel : ViewModel() {
    private val _errorEvent = MutableEventLiveData<String>()
    val errorEvent: EventLiveData<String>
        get() = _errorEvent

    fun fireErrorEvent(errorMessage: String) {
        _errorEvent.postEvent(errorMessage)
    }
    ...
}

class YourActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        //Note!!! EventObserver handles events not Observer
        viewModel.errorEvent.observe(this, EventObserver { 
            errorMessage -> showErrorMessage(errorMessage)
        })
    }
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接