因此,在iOS
开发中,我使用ReactiveCocoa
并使用该框架,我能够观察多个NSObjects
并将它们组合成一个返回值的signal
。像这样:
-(RACSignal *)modelIsValidSignal {
return [RACSignal combineLatest:@[RACObserve(self,username), RACObserve(self,password), RACObserve(self, busyLoggingIn)]
reduce:^id(NSString *username, NSString *password, NSNumber *busyLoggingIn) {
return @((username.length > 0) && (password.length > 0 && busyLoggingIn.boolValue == NO));
}];
}
因此,这将返回boolean
,该值为false或true。只要其中一个对象状态发生变化,就会通知此信号,然后subscriber (Observer)
将获得布尔值的当前值。
如何使用LiveData
执行类似的操作?最接近这一点的是MediatorLiveData
但是,我不知道如何同时观察多个LiveData
事件然后减少它,就像上面的例子一样。
答案 0 :(得分:4)
我做了一些像这样的验证
var firstName: MutableLiveData<String> = MutableLiveData()
var lastName: MutableLiveData<String> = MutableLiveData()
var personalDetailsValid: MediatorLiveData<Boolean> = MediatorLiveData()
personalDetailsValid.addSource(firstName, {
personalDetailsValid.value = lastName.value?.isNotBlank() == true && it?.isNotBlank() ?: false
})
personalDetailsValid.addSource(lastName, {
personalDetailsValid.value = firstName.value?.isNotBlank() == true && it?.isNotBlank() ?: false
})
然后我观察通常的方式
viewModel.personalDetailsValid.observe(this, Observer {
if (it == true) {
//Do something
}
})
我不知道这是否是推荐的使用LiveData和MediatorLiveData的方式,但它对我有用。
答案 1 :(得分:1)
方便且安全的解决方案:
fun <T1, T2, R> combine(
liveData1: LiveData<T1>,
liveData2: LiveData<T2>,
combineFn: (value1: T1?, value2: T2?) -> R
): LiveData<R> = MediatorLiveData<R>().apply {
addSource(liveData1) {
value = combineFn(it, liveData2.value)
}
addSource(liveData2) {
value = combineFn(liveData1.value, it)
}
}
fun <T1, T2, R> Pair<LiveData<T1>, LiveData<T2>>.map(
combineFn: (value1: T1?, value2: T2?) -> R
) = combine(first, second, combineFn)
使用示例:
val greetLine = combine(nameLiveData, surnameLiveData) { name, surname ->
"Hello, $name $surname!"
}
// or using map extension function for consistency with LiveData api
val greetLine = (nameLiveData to surnameLiveData).map { name, surname ->
"Hello, $name $surname!"
}
答案 2 :(得分:0)
我已经为2个(和更多)LiveData值实现了一些util方法。在以RX Observable.combineLatest()
方式工作的情况下,这意味着如果观察到的LiveData
之一将发出任何新值,它将触发更新的值。我添加了Function2
作为“合并器”函数(在我的情况下,我可以轻松使用RX.BiFunction,但是LiveData
可以发出null
值)。
合并两个LiveData
中的值的示例。
object LiveDataUtils {
fun <T1, T2, R> combineLatest(source1: LiveData<T1>,
source2: LiveData<T2>,
combiner: Function2<T1, T2, R>): LiveData<R> {
val mediator = MediatorLiveData<R>()
val combinerFunction = {
val source1Value = source1.value
val source2Value = source2.value
mediator.value = combiner.apply(source1Value, source2Value)
}
mediator.addSource(source1) { combinerFunction() }
mediator.addSource(source2) { combinerFunction() }
return mediator
}
}
interface Function2<T1, T2, R> {
fun apply(t1: T1?, t2: T2?): R
}