RxJava, good use case for flat map

I'm new to RxJava, often confused by the flatMap function. According to doc , flatmaptransform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

Can anyone provide a good use case for this? Why convert the original Observable to Observables (plural) and then turn them into a single Observable.

Why don't you just use the "map"?

If you give an example on Android it's amazing, otherwise plain Java will be good enough. Thanks to

+3


source to share


3 answers


Let's say you have

Observable<Foo> fooObservable;

      

And you want to call another method that takes Foo

and emitsObservable<Bar>

Something like:

public Observable<Bar> getBars(Foo foo);

      



If you did this:

fooObservable.map(foo -> getBars(foo));

      

As a result you get Observable<Observable<Bar>>

, because you have changed your Foo

Observable<Bar>

, which is probably not the one you want.

Instead, you can use flatMap

which "flattens observables":

Observable<Bar> barObservable = fooObservable.flatMap(foo -> getBars(foo));

      

+6


source


I see the tag Android

for your question. So, you should probably be familiar with Retrofit

.

Let's say you have 2 methods:

public interface FoxreyRestApi {

    @POST("/signin")
    Observable<SignInResponse> signin(@Body SignInRequest request);

    @GET("/user")
    Observable<User> getUser(String accessToken);
}

      

You want to get user data, but you need accessToken

to return which SignInResponse

.



You can do it:

1). Create RestAdapter

.

2). Makes requests one - after - another:

restAdapter.signin(request)
    .flatMap(r -> restAdapter.getUser(r.getAccessToken()))
    .subscribe(user -> {/*User your user*/});

      

+20


source


Very often I use it to convert some UI events to observable background tasks:

ViewObservable.clicks(calculateBtn)
    .flatMap(new Func1<OnClickEvent, Observable<Integer>>() {
      @Override
      public Observable<Integer> call(OnClickEvent onClickEvent) {
          return observeBackgroundOperation()
            .observeOn(AndroidSchedulers.mainThread())//interaction with UI must be performed on main thread
            .doOnError(new Action1<Throwable>() {//handle error before it will be suppressed
                @Override
                public void call(Throwable throwable) {
                    progress.setVisibility(View.GONE);
                    calculateBtn.setEnabled(true);
                    Toast.makeText(IOCombineSampleActivity.this, R.string.mix_error_message, Toast.LENGTH_SHORT).show();
                }
            })
            .onErrorResumeNext(Observable.<Integer>empty());//prevent observable from breaking
      }
    })
    .subscribe(new Action1<Integer>() {...});

      

Since it is easy to define background operations with an observable, I used flatMap

to convert button click events to "something that was done in background events" (for example, a network request was completed with Retrofit) and then watch them.

Note that the observable in flatMap

can emit one value, which is executed in the sample.

This way I declaratively define the interaction between UIs and background processes. I handle errors with doOnError

and then use onErrorResumeNext(Observable.<Integer>empty())

to prevent observing with terminated with onError

. As I am using flatMap

, my observable is not complete (while the inner one flatMap

was) and is waiting for the next click events.

You can find a complete code sample in my article .

+1


source







All Articles