如何停止多次触发 LiveData 事件

How to stop LiveData event being triggered more than Once

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

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

如何避免这个问题?任何 help/suggestions 都非常感谢! 谢谢。

您可以使用 Event 包装 LiveData 值来处理使用其值的问题,如下文所示: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

事件 class 会像:

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>>()

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

接受答案的问题是你只能有一个观察者。 article 描述了具有多个观察者的解决方案。

我遇到了同样的问题,想出了这个库来解决它 https://github.com/ueen/LiveEvent 希望这对您有所帮助,祝您愉快!

简单、干净、可重复使用:

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