capt.swag
capt.swag

Reputation: 10661

Any Rx operator which could FlatMap and return both the output

I want to know if there's an appropriate RxJava operator for my use-case. I have the below two methods. These are retrofit interfaces.

fun getSources(): Single<Sources>
fun getTopHeadlines(sourceCsv: String): Single<TopHeadlines>

Currently I'm doing this

getSources()
    .map { sources -> 
        // convert the sources list to a csv of string 
    }
    .flatMap { sourcesCsv
        getTopHeadlines(sourcesCsv)
    }
    .subsribe {topHeadlines, error -> }

This works well and good, if my objective is to get the top headlines. But what I'm instead trying to get is both the sources as well as top headlines while subscribing to it? Is there any operator that I'm not aware off or is there any other way of doing the same?

Upvotes: 1

Views: 810

Answers (2)

Sergej Isbrecht
Sergej Isbrecht

Reputation: 4012

As an addition to mohsens answer:

You do not need to zip it. Just use another map operator inside the flatMap and combine both values to a Pair, just as I did in this example:

import io.reactivex.rxjava3.core.Single
import org.junit.jupiter.api.Test

class So65640603 {
    @Test
    fun `65640603`() {
        getSources()
            .flatMap { source -> getTopHeadlines(source).map { headLines -> source to headLines } }
            .test()
            .assertValue("v1" to 42)
    }
}

fun getSources(): Single<String> {
    return Single.just("v1")
}

fun getTopHeadlines(sourceCsv: String): Single<Int> {
    return Single.just(42)
}

Upvotes: 1

Mohsen
Mohsen

Reputation: 1389

you can use the zip() method to do this. zip waits for both items then emits the required value. you can use it like this

getSources()
    .map { sources -> 
        // convert the sources list to a csv of string 
    }
    .flatMap { sourcesCsv ->
        Single.zip(
            Single.just(sourcesCsv),
            getTopHeadlines(sourcesCsv),
            BiFunction { t1, t2 -> Pair(t1, t2) }
        )
    }
    

then when you subscribe to this you have both values as a Pair. you can make an extension function for it and make you life easier:

fun <T, V> Single<T>.zipWithValue(value: V) = Single.zip(
    Single.just(value),
    this,
    { t1, t2 -> Pair(t1, t2) }
)

and inside your flatMap you can do getTopHeadlines(sourcesCsv).zipWithValue(sourcesCsv). the same could be done for Maybe, and for Flowabale you can use combineLatest() method.

Upvotes: 2

Related Questions