将多个实时数据值映射到一个

因此,在开发中,我使用并且通过该框架,我能够观察多个并将它们组合成返回值的a。像这样:iOSReactiveCocoaNSObjectssignal

-(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));
                             }];
}

因此,这将返回一个 false 或 true。一旦其中一个对象状态发生变化,就会通知此信号,然后获取布尔值的当前值。booleansubscriber (Observer)

如何使用 ?最接近这样做的是,但是,我不明白如何同时观察多个事件,然后减少它,就像上面的例子一样。LiveDataMediatorLiveDataLiveData


答案 1

我做了一些这样的验证

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和MeditorLiveData的推荐方式,但它对我有用。


答案 2

方便安全的解决方案:

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!"
}

推荐