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

3

8

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?

Tekla answered 24/10, 2017 at 22:12 Comment(0)
T
7

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)
Tomblin answered 25/10, 2017 at 6:6 Comment(5)
This issue might be of interest "Dealing with necessary SAM adapters with RxJava2" github.com/ReactiveX/RxKotlin/issues/103Tomblin
Can you post the whole statement? (the whole temp() method from my question)I am afraid it doesn't workTekla
Updated to include the whole temp method @oksetTomblin
Thanks, i also tried this but not worked. What worked for me was this: Function3<List<String>, List<Int>, Boolean, Boolean> { t1, t2, t3 -> saveEvents(t1, t2, t3)Tekla
I'll update the answer to what worked for you. It may depend on the version of Kotlin as to whether the explicit type arguments are requiredTomblin
M
0

Thanks to @Joeleski I found a bug. In my case I specified type explicitly to every parameter of a zip operator, then found that one variable had a wrong type.

Mark answered 8/5, 2018 at 13:12 Comment(0)
M
0

For who it may concern....

I had this issue when trying to execute Observable.merge()

The solution was changing it to Observable.mergeArray()

Mima answered 18/6, 2019 at 22:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.