Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava flatMapIterable with a Single

I'm trying to tidy up my code a little, and Single is looking like a good choice for me as I'm doing something that will only ever emit one result.

I'm having an issue though as I was using flatMapIterable previously to take my response (a list) and do something on each item. I'm not seeing how I can achieve this with Single.

getListOfItems()
.flatMapIterable(items -> items)
.flatMap(item -> doSomethingWithItem())
.toList()

This works fine if getListOfItems is returning an Observable but if I try and make it return a Single, then I can't do flatMapIterable and can't see an alternative, any ideas?

like image 219
spO_oks Avatar asked Mar 14 '17 12:03

spO_oks


People also ask

What is a single in RxJava?

RxJava (and its derivatives like RxGroovy & RxScala) has developed an Observable variant called “Single.” A Single is something like an Observable, but instead of emitting a series of values — anywhere from none at all to an infinite number — it always either emits one value or an error notification.

How do you convert single to Observable?

If I understood correctly, you want to convert Single<List<Item>> into stream of Item2 objects, and be able to work with them sequentially. In this case, you need to transform list into observable that sequentially emits items using . toObservable(). flatMap(...) to change the type of the observable.

What is flatMapIterable?

flatMapIterable : Maps the values of the upstream source into Iterable s and iterates each of them one after the other. In other words, it merges dynamically generated pull sources. You can express flatMapIterable as flatMap(Observable::fromIterable) or concatMap(Observable::fromIterable) .


3 Answers

flattenAsObservable should do the trick, it will map Single success value to Iterable (list), and emit each item of the list as an Observable.

  getListOfItems()
            .flattenAsObservable(new Function<Object, Iterable<?>>() {
                @Override
                public Iterable<?> apply(@NonNull Object o) throws Exception {
                    return toItems(o);
                }
            })
            .flatMap(item -> doSomethingWithItem())
            .toList()
like image 78
yosriz Avatar answered Oct 19 '22 09:10

yosriz


Building on the answer from yosriz, this is what I ended up with in Kotlin

getListOfItems()
        .flattenAsObservable { it }
        .flatMap { doSomethingWithItem(it) }
        .toList()

The same can be achieved using Kotlin's map, depending on your preference:

getListOfItems()
        .map { items ->
            items.map {
                doSomethingWithItem(it)
            }
        }
like image 43
Sebastian Avatar answered Oct 19 '22 10:10

Sebastian


You can convert Single to Observable by using operator toObservable()

It will look like this:

getListOfItems()
    .toObservable()
    .flatMapIterable(items -> items)
    .flatMap(item -> doSomethingWithItem())
    .toList()
like image 4
TermLog Avatar answered Oct 19 '22 10:10

TermLog