Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use "if-else" in RX java chain?

Tags:

I am a newer on RXJava/RXAndroid. I want to implement this case: chose different way based on some condition in RXJava. For example, first, I fetch user info from network and if this is a VIP user, I will go on to fetch more info from network or just show some info in main thread (break the chain.) Here the flow chart: https://i.stack.imgur.com/0hztR.png

I do some search on this and only find "switchIfEmpty" may help. I write the following code:

getUserFromNetwork("userId")                 .flatMap(new Function<User, ObservableSource<User>>() {                     @Override                     public ObservableSource<User> apply(User user) throws Exception {                         if(!user.isVip){                             //show user info on MainThread!                             return Observable.empty();                         }else{                             return getVipUserFromNetwork("userId");                         }                     }                 }).switchIfEmpty(new ObservableSource<User>() {                     @Override                     public void subscribe(Observer<? super User> observer) {                         //show user info in main thread                         //just break the chain for normal user                         observer.onComplete();                     }                 }).doOnNext(new Consumer<User>() {                     @Override                     public void accept(User user) throws Exception {                         //show vip user info in main thread                     }                 }).subscribe(); 

Is there more simple way to achieve this?

Thanks!

like image 410
niu yi Avatar asked Apr 13 '17 02:04

niu yi


1 Answers

flatMap() is a good choice, you can split the stream with it, but at the end the stream merges together (all emissions from each split observable flows to the main stream). In your code, the switchIfEmpty() is redundant as that's exactly what Observable.empty() do (invoke immediately the onCompleted()), and also you need of course observer on, if you want the display to happen on main thread, but anyhow, I think it's not a good practice to handle this in the middle of the stream.

I think that in your case, you can handle (react to) the user emission in single handler, as it's very similar, just check if that's VIP or not and display it accordingly. so it should look something like this:

getUserFromNetwork("userId")             .flatMap(new Function<User, ObservableSource<User>>() {                 @Override                 public ObservableSource<User> apply(User user) throws Exception {                     if (!user.isVip) {                         return Observable.just(user);                     } else {                         return getVipUserFromNetwork("userId");                     }                 }             })             .observeOn(AndroidSchedulers.mainThread())             .subscribe(user -> {                 if (user.isVip){                     //display vip user                 }else{                     //display regular user                 }             }); 

in this approach you have a single stream flow, without 'side effects' in the middle of the stream.

In case you're handling is totally different (which is not this case), then you can split the stream to 2 separated streams and react to each one differently, this can be done by multicast your getUserFromNetwork() Observable, and from this Observable create 2 different Observable, one that will continue for example getVipUserFromNetwork(), and one that don't, and each can have different subscriber logic. (you can read here my answer regarding multicasting)

like image 124
yosriz Avatar answered Oct 14 '22 06:10

yosriz