5

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

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

如何避免这个问题?任何帮助/建议都非常感谢!谢谢你。

4

5 回答 5

5

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

事件类就像:

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

于 2019-02-14T11:03:16.963 回答
0

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

于 2019-02-14T11:26:43.200 回答
0

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

于 2020-01-09T03:36:18.653 回答
0

我遇到了同样的问题并想出了这个库来解决它 https://github.com/ueen/LiveEvent 希望这有帮助,享受!

于 2020-01-18T00:14:21.090 回答
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)
        })
    }
    ...
}
于 2021-11-11T12:30:43.817 回答