Reputation: 29867
I have 4 text input fields. When the user enters text into any of the fields, I will enable a button. To accomplish this, I will use the combineLatest by combining 4 observables that receive text in their streams. I am at a loss as to how to access the latest value of each of the observables. NOTE: I want to use an array as eventually there will be more than 4 input fields. I am also looking for a solution in Kotlin.
val text1: PublishSubject<String> = PublishSubject.create()
val text2: PublishSubject<String> = PublishSubject.create()
val text3: PublishSubject<String> = PublishSubject.create()
val text4: PublishSubject<String> = PublishSubject.create()
val inputs = Arrays.asList(
text1, text2, text3, text4
)
Observable.combineLatest(inputs) {
// How do I access the latest value from each observable?
}
Upvotes: 1
Views: 5833
Reputation: 194
You can use any of these extension functions:
// [publisher1, publisher2].combineLatest()
extension Array where Element: Publisher {
func combineLatest() -> AnyPublisher<[Element.Output], Element.Failure> {
Publishers.CombineLatestArray(self)
}
}
// Publishers.CombineLatestArray([publisher1, publisher2])
extension Publishers {
static func CombineLatestArray<P>(_ array: [P]) -> AnyPublisher<[P.Output], P.Failure> where P : Publisher {
array.dropFirst().reduce(into: AnyPublisher(array[0].map{[$0]})) { res, ob in
res = res.combineLatest(ob) { i1, i2 -> [P.Output] in
return i1 + [i2]
}.eraseToAnyPublisher()
}
}
}
Upvotes: 1
Reputation: 6988
You can combine them and provide a function to wrap the values into a custom class:
Observable.combineLatest(
text1,
text2,
text3,
text4,
Function4<String, String, String, String, LatestResult> { t1, t2, t3, t4 ->
LatestResult(t1, t2, t3, t4)
})
.subscribe { latestResult ->
// Access the latest results here:
println(latestResult.text1)
println(latestResult.text2)
println(latestResult.text3)
println(latestResult.text4)
}
}
data class LatestResult(val text1: String, val text2: String, val text3: String, val text4: String)
Upvotes: 0
Reputation: 2822
Inside the lambda you get an array. The i-th element of this array (arrayOfEmissions
in the following example) corresponds to the latest element emitted by the i-th observable.
Observable.combineLatest(inputs) { arrayOfEmissions ->
}
Upvotes: 3