17
votes

I want to create an Observable which emits some items from and Observable containing list of objects with Interval Observable, so that the items from the first observable will be emitting with some time delay. Here is my implementation:

 val just1 = ArrayList<SomeClass1>()

populate some items

fun populateJust1() {
just1.add(SomeClass1("23", 23))
just1.add(SomeClass1("24", 24))
just1.add(SomeClass1("25", 25))
}

populateJust1()

and zip with the interval Observable

Observable.fromIterable(just1)
            .zipWith(Observable.interval(2, TimeUnit.SECONDS)) { item: SomeClass1, interval: Long -> item }
            .subscribe(Consumer<SomeClass1> { someClass1 -> Log.v("someClass1", someClass1.toString()) })

However the IDE, Android Studio 3.0 underlines in red the zipWith operator and says:

None of the following functions can be called with the arguments supplied. zipWith(((observer: Observer) → Unit)!, ((t1: SomeClass1, t2: Long) → R)!)   where R cannot be inferred; U = Long for   fun zipWith(other: ((observer: Observer) → Unit)!, zipper: ((t1: SomeClass1, t2: U) → R)!): Observable! defined in io.reactivex.Observable zipWith(ObservableSource!, BiFunction!)   where R cannot be inferred; U = Long! for   fun zipWith(other: ObservableSource!, zipper: BiFunction!): Observable! defined in io.reactivex.Observable zipWith((Mutable)Iterable!, BiFunction!)   where U, R cannot be inferred for   fun zipWith(other: (Mutable)Iterable!, zipper: BiFunction!): Observable! defined in io.reactivex.Observable zipWith((Mutable)Iterable!, ((t1: SomeClass1, t2: Long) → R)!)   where R cannot be inferred; U = Long for   fun zipWith(other: (Mutable)Iterable!, zipper: ((t1: SomeClass1, t2: U) → R)!): Observable! defined in io.reactivex.Observable

What is wrong? I've just converted this code from Java class where everything was correct

2

2 Answers

28
votes

Kotlin can't infer the types in that zipWith lambda.

Use a BiFunction instead of the lambda:

data class SomeClass(val a: String, val b: Int)

val list = listOf(SomeClass("1", 1), SomeClass("2", 2))

Observable
        .fromIterable(list)
        .zipWith(Observable.interval(2, TimeUnit.SECONDS),
                BiFunction { item: SomeClass, _: Long -> item })
        .subscribe { Log.v("someClass", it.toString())
10
votes

You could also use RxKotlin that comes with some small wrappers to hide this kind of noise. Here is an example for the Single.zipWith:

fun <T, U> Single<T>.zipWith(other: SingleSource<U>): Single<Pair<T,U>>
    = zipWith(other, BiFunction { t, u -> Pair(t,u) })