Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin and RxJava2 zip operator - None of the following functions can be called with the arguments supplied

I have a problem with writing the .zip Observable in Kotlin using Android Studio 3.0 IDE.

Here is my code:

internal var updateStringEventsSubject = PublishSubject.create<String>()
internal var updateIntEventsSubject = PublishSubject.create<Int>()

internal var triggerSave = PublishSubject.create<Boolean>()
internal var triggerStopAndSave = PublishSubject.create<Boolean>()

internal var normalSaveTrigger = triggerSave.debounce(30, TimeUnit.SECONDS)
internal var trigger = Observable.merge(normalSaveTrigger, triggerStopAndSave)

private fun saveEvents(
        strings: List<String>,
        integers: List<Int>,
        someBoolean: Boolean): Boolean {

    return true //doesn't matter for now
}

fun temp() {
    Observable.zip<List<String>, List<Int>, Boolean, Boolean>(updateStringEventsSubject.buffer(trigger),
            updateIntEventsSubject.buffer(trigger),
            trigger, { strings: List<String>, integers: List<Int>, someBoolean: Boolean -> saveEvents(strings, integers, someBoolean) })
            .subscribe()
}

However, my IDE(Android Studio 3.0 RC2) underlines the .zip operator and says:

None of the following functions can be called with the arguments supplied. zip(((observer: Observer!>) → Unit)!, ((observer: Observer!>) → Unit)!, ((observer: Observer) → Unit)!, ((t1: List, t2: List, t3: Boolean) → Boolean)!)   where T1 = List, T2 = List, T3 = Boolean, R = Boolean for   fun zip(source1: ((observer: Observer) → Unit)!, source2: ((observer: Observer) → Unit)!, source3: ((observer: Observer) → Unit)!, zipper: ((t1: T1, t2: T2, t3: T3) → R)!): Observable! defined in io.reactivex.Observable zip(((observer: Observer!>) → Unit)!, ((observer: Observer!>) → Unit)!, ((t1: List, t2: List) → Boolean)!, Boolean)   where T1 = List, T2 = List, R = Boolean for   fun zip(source1: ((observer: Observer) → Unit)!, source2: ((observer: Observer) → Unit)!, zipper: ((t1: T1, t2: T2) → R)!, delayError: Boolean): Observable! defined in io.reactivex.Observable zip(ObservableSource!>!, ObservableSource!>!, ObservableSource!, io.reactivex.functions.Function3!, in List!, in Boolean!, out Boolean!>!)   where T1 = List, T2 = List, T3 = Boolean, R = Boolean for   fun zip(source1: ObservableSource!, source2: ObservableSource!, source3: ObservableSource!, zipper: Function3!): Observable! defined in io.reactivex.Observable zip(ObservableSource!>!, ObservableSource!>!, BiFunction!, in List!, out Boolean!>!, Boolean)   where T1 = List, T2 = List, R = Boolean for   fun zip(source1: ObservableSource!, source2: ObservableSource!, zipper: BiFunction!, delayError: Boolean): Observable! defined in io.reactivex.Observable

How to make it work with Kotlin?

like image 940
K.Os Avatar asked Oct 24 '17 22:10

K.Os


1 Answers

For some reason using RxJava 1.1.7 it considers explicitly specifying the type of zipper argument as Func3 a redundant SAM-constructor (which it is) and allows you to replace it with a lambda. However, using RxJava 2.1.5 the type changes to Function3 and it no longer recognises it as an interface with a single abstract method (which it still is). I'm not sure why that is.

Regardless, specifying the type of the zipper function will do the trick:

import io.reactivex.functions.Function3
...

fun temp() {
    Observable.zip<List<String>, List<Int>, Boolean, Boolean>(updateStringEventsSubject.buffer(trigger),
            updateIntEventsSubject.buffer(trigger),
            trigger, Function3 { strings, integers, someBoolean -> saveEvents(strings, integers, someBoolean) } )
            .subscribe()
}

Note: I managed to get it to work without explicitly specifying the type arguments for Function3. It may depend on which version of Kotlin or RxJava you're using as to whether it can infer the types. If not you can always be more explicit:

Function3<List<String>, List<Int>, Boolean, Boolean> { ... }

Edit: There's an even easier way: Use io.reactivex.rxkotlin.Observables instead. It's an inline function that does the ugly type declaration under the hood for us. Then you can just do this:

import io.reactivex.rxkotlin.Observables
...

Observables.zip(updateStringEventsSubject.buffer(trigger),
                updateIntEventsSubject.buffer(trigger),
                trigger, 
                ::saveEvents)
like image 87
Joeleski Avatar answered Sep 30 '22 17:09

Joeleski