Search code examples
androidkotlinrx-javarx-java2

Observable.combineLatest cause error after updating to RxJava 2.x.x. - cannot infer type


Last few days I am trying to migrate my project from RxJava 1.x.x to RxJava 2.x.x. I have this simple method. Everything is OK if I use the Observables from rxjava 1.x.x (rx.Observable). However, when I replaced it with "new" observables (io.reactivex.Observable, I get an error saying : "Type inference failed. Please specify it explicitly"

fun <T1, T2, T3, R> combineLatestValue3Nullable(observable1: Observable<T1?>, observable2: Observable<T2?>, observable3: Observable<T3?>, merge: (T1, T2, T3?) -> R): Observable<R?> {
    return Observable.combineLatest(observable1, observable2, observable3) {
        value1, value2, value3 ->
        var result: R? = null
        if (value1 != null && value2 != null) {
            result = merge(value1, value2, value3)
        }
        result
    }
}

Do you have any idea what I do wrong? Can you please explain what exactly cause this error in RxJava 2?

Somebody (here) had a problem very similar to this. However, they are using BiFuntion in their solution which accepts two arguments and creates a result. As you can see I use more arguments (3) so I can't use Bifunction here.


Solution

  • In the end I found a solution based on given advice above. The first thing which should be mentioned is the fact that we shouldn't return nullable Observable at all. If we need to check values passed to combineLatest we should do it before instead of checking it inside combineLatest.

    When we remove nullability the method looks like this:

    fun <T1, T2, T3, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, merge: (T1, T2, T3) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, Function3 {
            value1, value2, value3 ->
            merge(value1, value2, value3)
        })
    }
    

    The only additional thing which I had to change is to replace lambda with Function3 - it solves the problem of type inference.

    If you have just two values for combineLatest you can use BiFuntion instead of Function3.

    If you need to pas for example 6 variables to combineLatest you can use Function6 etc.

    See all the variants below:

    fun <T1, T2, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, merge: (T1, T2) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, BiFunction {
            value1, value2 ->
            merge(value1, value2)
        })
    }
    
    fun <T1, T2, T3, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, merge: (T1, T2, T3) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, Function3 {
            value1, value2, value3 ->
            merge(value1, value2, value3)
        })
    }
    
    fun <T1, T2, T3, T4, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, observable4: Observable<T4>, merge: (T1, T2, T3, T4) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, observable4, Function4 {
            value1, value2, value3, value4 ->
            merge(value1, value2, value3, value4)
        })
    }
    
    fun <T1, T2, T3, T4, T5, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, observable4: Observable<T4>, observable5: Observable<T5>, merge: (T1, T2, T3, T4, T5) -> R): Observable<R> {
    
        return Observable.combineLatest(observable1, observable2, observable3, observable4, observable5, Function5 {
            value1, value2, value3, value4, value5 ->
            merge(value1, value2, value3, value4, value5)
        })
    }
    
    fun <T1, T2, T3, T4, T5, T6, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, observable4: Observable<T4>, observable5: Observable<T5>, observable6: Observable<T6>, merge: (T1, T2, T3, T4, T5, T6) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, observable4, observable5, observable6, Function6 {
            value1, value2, value3, value4, value5, value6 ->
            merge(value1, value2, value3, value4, value5, value6)
        })
    }
    
    fun <T1, T2, T3, T4, T5, T6, T7, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, observable4: Observable<T4>, observable5: Observable<T5>, observable6: Observable<T6>, observable7: Observable<T7>, merge: (T1, T2, T3, T4, T5, T6, T7) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, observable4, observable5, observable6, observable7, Function7 {
            value1, value2, value3, value4, value5, value6, value7 ->
            merge(value1, value2, value3, value4, value5, value6, value7)
        })
    }
    
    fun <T1, T2, T3, T4, T5, T6, T7, T8, R> combineLatest(observable1: Observable<T1>, observable2: Observable<T2>, observable3: Observable<T3>, observable4: Observable<T4>, observable5: Observable<T5>, observable6: Observable<T6>, observable7: Observable<T7>, observable8: Observable<T8>, merge: (T1, T2, T3, T4, T5, T6, T7, T8) -> R): Observable<R> {
        return Observable.combineLatest(observable1, observable2, observable3, observable4, observable5, observable6, observable7, observable8, Function8 {
            value1, value2, value3, value4, value5, value6, value7, value8 ->
            merge(value1, value2, value3, value4, value5, value6, value7, value8)
        })
    }