[ViewModel
和View
之间进行通讯的正确方式是什么,Google体系结构组件使用LiveData
,其中视图订阅更改并据此进行更新,但是这种通信不适用于单个事件,例如显示消息,显示进度,隐藏进度等。
[在Google的示例中有一些类似SingleLiveEvent
的骇客,但仅适用于1个观察者。一些开发人员使用EventBus
,但我认为当项目增长时,它很快就会失控。
有没有方便且正确的方法来实现它,您如何实现它?
[我已经将LiveData与Google代码实验室回购中Kotlin协程(ConsumableValue<T>
)的Link类的副本一起使用了很长一段时间,它为我提供了很好的帮助:
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 {
val oneShotData = MutableLiveData<ConsumableValue<String>>()
fun push(msg: String) = oneShotData.value = ConsumableValue(msg)
}
// In Fragment or Activity
viewModel.oneShotData.observe(this, Observer { value ->
value?.handle { Log("TAG", "Message:$it")}
})