android - MVVM中 View 和ViewModel之间的通信与LiveData

标签 android android-livedata android-architecture-components

ViewModel 之间的正确通信方式是什么?和 View , Google architecture components给予使用LiveData其中 View 订阅更改并相应地更新自身,但这种通信不适合单个事件,例如显示消息、显示进度、隐藏进度等。

有一些像 SingleLiveEvent 这样的 hack在谷歌的例子中,但它只适用于 1 个观察者。
一些开发者使用 EventBus但我认为随着项目的发展,它会很快失去控制。

有没有方便正确的实现方式,怎么实现的?

(也欢迎 Java 示例)

最佳答案

是的,我同意,SingleLiveEvent是一个 hacky 解决方案,EventBus(根据我的经验)总是会导致麻烦。

我找到了一个名为 ConsumableValue 的类不久前阅读 Google CodeLabs for Kotlin Coroutines 时,我发现它是一个很好的、干净的解决方案,对我很有帮助(ConsumableValue.kt):

class ConsumableValue<T>(private val data: T) {
    private var consumed = false

    /**
     * Process this event, will only be called once
     */
    @UiThread
    fun handle(block: ConsumableValue<T>.(T) -> Unit) {
        val wasConsumed = consumed
        consumed = true
        if (!wasConsumed) {
            this.block(data)
        }
    }

    /**
     * Inside a handle lambda, you may call this if you discover that you cannot handle
     * the event right now. It will mark the event as available to be handled by another handler.
     */
    @UiThread
    fun ConsumableValue<T>.markUnhandled() {
        consumed = false
    }
}
class MyViewModel : ViewModel {
    private val _oneShotEvent = MutableLiveData<ConsumableValue<String>>()
    val oneShotEvent: LiveData<ConsumableValue<String>>() = _oneShotData

    fun fireEvent(msg: String) {
        _oneShotEvent.value = ConsumableValue(msg)
    }
}
// In Fragment or Activity
viewModel.oneShotEvent.observe(this, Observer { value ->
    value?.handle { Log("TAG", "Message:$it")}
})

简而言之,handle {...} block 只会被调用一次,因此如果您返回屏幕,则无需清除该值。

关于android - MVVM中 View 和ViewModel之间的通信与LiveData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59057941/

相关文章:

android - Gradle 设置 : Invalid variable name. 必须以字母开头,但是:

java - youtube api 显示 channel 视频 android

android - 在 Repository 和 ViewModel 之间共享相同的 MutableLiveData

android - ViewModelProvider.NewInstanceFactory - 接收相同的实例

android - 使用 LiveData 而不是常规回调有什么好处吗?

java - 如何在android代码中读取和写入用户可访问的目录?

android - 在另一个 tabview 内的 Tabview 内打开 alertDialog

kotlin - 在从暂停的存储库中获取的 ViewModel 中传递 LiveData 的正确方法

android - 在 Android 中检测空的 PagedList 结果

android - 使用新的 MotionLayout 模仿 Snackbar + CoordinatorLayout + FAB