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
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));
      
        
        
        
      
     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*/});
      
        
        
        
      
     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 .