Johann
Johann

Reputation: 29867

Use combineLatest with an array of observables

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

Answers (3)

kumar shivang
kumar shivang

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

Gustavo Pagani
Gustavo Pagani

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

gpunto
gpunto

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

Related Questions