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/