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