如何使用;如有其他",;在RX java链中?

如何使用;如有其他",;在RX java链中?,java,android,rx-java,rx-android,rx-java2,Java,Android,Rx Java,Rx Android,Rx Java2,我是RXJava/RXAndroid上的新手。我想实现这个案例:根据RXJava中的某些条件选择不同的方式。 例如,首先,我从网络中获取用户信息,如果这是VIP用户,我将继续从网络中获取更多信息,或者只是在主线程中显示一些信息(断开链)。下面是流程图: 我对此做了一些搜索,只找到“switchIfEmpty”可能会有所帮助。 我编写以下代码: getUserFromNetwork("userId") .flatMap(new Function<User, O

我是RXJava/RXAndroid上的新手。我想实现这个案例:根据RXJava中的某些条件选择不同的方式。 例如,首先,我从网络中获取用户信息,如果这是VIP用户,我将继续从网络中获取更多信息,或者只是在主线程中显示一些信息(断开链)。下面是流程图:

我对此做了一些搜索,只找到“switchIfEmpty”可能会有所帮助。 我编写以下代码:

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();
getUserFromNetwork(“用户ID”)
.flatMap(新函数(){
@凌驾
公共可观测资源应用(用户)引发异常{
如果(!user.isVip){
//在主线程上显示用户信息!
return-Observable.empty();
}否则{
返回getVipUserFromNetwork(“用户ID”);
}
}
}).switchIfEmpty(新的可观察资源(){
@凌驾
public void subscribe(Observer
flatMap()
是一个很好的选择,您可以使用它分割流,但最终流合并在一起(每个分割的可观测流的所有排放都流向主流)。 在代码中,
开关ifempty()
是多余的,因为这正是
可观察的.empty()
要做的(立即调用
onCompleted()
)当然,如果你想让显示发生在主线程上,当然也需要观察者,但无论如何,我认为在流中间处理这不是一个好的实践。 我认为在您的情况下,您可以在单个处理程序中处理(反应)用户发射,因为它非常相似,只需检查它是否为VIP,并相应地显示它。 所以它应该是这样的:

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
                }
            });
getUserFromNetwork(“用户ID”)
.flatMap(新函数(){
@凌驾
公共可观测资源应用(用户)引发异常{
如果(!user.isVip){
返回可观察的。仅(用户);
}否则{
返回getVipUserFromNetwork(“用户ID”);
}
}
})
.observeOn(AndroidSchedulers.mainThread())
.订阅(用户->{
if(user.isVip){
//显示vip用户
}否则{
//显示普通用户
}
});

在这个方法中,你有一个单一的流流,在流中间没有“副作用”。


如果您处理的是完全不同的(不是这种情况),那么您可以将流拆分为两个分离的流,并对每个流做出不同的反应,这可以通过多播您的
getUserFromNetwork()来完成
Observable,并由此创建两个不同的
Observable
,一个将继续,例如
getVipUserFromNetwork()
,另一个不继续,每个都可以有不同的订户逻辑。(您可以阅读我关于多播的回答)

我最近发现了switchIfEmpty操作符,它适合我的需要,可能对某些人有用。Rx对我来说仍然是一种新的思维方式,因此我也愿意听取建议和意见。 让我试着给你另一种思考的方式。正如@yosriz指出的,在随后的onComplete中使用switchIfEmpty是多余的

正如名字所说,switchIfEmpty当基本的一个完成而不发出任何值时,它会切换到另一个可观察的

以下是两种情况:

  • 可观察对象发出一个值,然后完成
  • 可观察到的数据在不发出值的情况下完成
诀窍是使用空流作为谓词

给定一个用作谓词的基本可观察对象,如果过滤它的发射,可以将switchIfEmpty操作符链接到回退流

在以下代码中,“用户”和“VIP用户”共享相同的界面/类。 即使我使用Java8Lambdas来编写代码,请注意没有if语句

  // User Observable, cached so only 1 network call is done
Observable<User> user = getUserFromNetwork("USER_ID").cache();
  // This observable is the user's VIP Status as a boolean stream
Observable<Boolean> isVip = user.map(u -> u.isVip() );
这是完整的代码

Observable<User> user = getUserFromNetwork("USER_ID").cache();
Observable<Boolean> isVip = user.map(u -> u.isVip() );

Observable<User> vipUser = isVip
    .filter(vip -> vip)
    .flatMap(vip -> user.flatMap(usr -> {
        return getVipUserFromNetwork(usr.getId());
    }));
});

vipUser.switchIfEmpty(user)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(usr -> {
        // Handle UI Changes
    });
Observable user=getUserFromNetwork(“user_ID”).cache();
可观测isVip=user.map(u->u.isVip());
可观察的振动=isVip
.过滤器(vip->vip)
.flatMap(vip->user.flatMap(usr->{
返回getVipUserFromNetwork(usr.getId());
}));
});
vipUser.switchIfEmpty(用户)
.observeOn(AndroidSchedulers.mainThread())
.订阅(usr->{
//处理UI更改
});

这是您能做的最好的了。您的代码没有问题。
vipUser.switchIfEmpty(user)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(usr -> {
        // Logging the class just to understand the outcome
        System.out.println("User instanceOf " + usr.getClass());
    });
Observable<User> user = getUserFromNetwork("USER_ID").cache();
Observable<Boolean> isVip = user.map(u -> u.isVip() );

Observable<User> vipUser = isVip
    .filter(vip -> vip)
    .flatMap(vip -> user.flatMap(usr -> {
        return getVipUserFromNetwork(usr.getId());
    }));
});

vipUser.switchIfEmpty(user)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(usr -> {
        // Handle UI Changes
    });