如何在 RX java 链中使用 "if-else"?
How to use "if-else" in RX java chain?
我是 RXJava/RXAndroid 的新手。我想实现这种情况:根据 RXJava 中的某些条件选择不同的方式。
例如,首先,我从网络中获取用户信息,如果这是 VIP 用户,我将继续从网络中获取更多信息,或者只在主线程中显示一些信息(打破链条。)这里的流程图:https://i.stack.imgur.com/0hztR.png
我对此做了一些搜索,只发现 "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();
有没有更简单的方法来实现这个?
谢谢!
flatMap()
是一个不错的选择,你可以用它拆分流,但最后流合并在一起(每个拆分的可观察到的所有排放都流向主流)。
在您的代码中,switchIfEmpty()
是多余的,因为这正是 Observable.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
}
});
在这种方法中,您只有一个流,流中间没有 'side effects'。
如果你处理的是完全不同的(这不是这种情况),那么你可以将流拆分为 2 个独立的流并对每个流做出不同的反应,这可以通过多播你的 getUserFromNetwork()
可观察,并从这个 Observable
创建 2 个不同的 Observable
,一个将继续,例如 getVipUserFromNetwork()
,一个不会,每个都可以有不同的订阅者逻辑。 (你可以阅读 我关于多播的回答)
我最近发现了 switchIfEmpty 运算符,它适合我的需要并且可能对某些人有用。 Rx 对我来说仍然是一种新的思维方式,所以我也愿意接受建议和评论。
让我试着给你另一种思考方式。正如@yosriz 指出的那样,使用 switchIfEmpty 和随后的 onComplete 是多余的。
顾名思义,switchIfEmpty 当基本对象完成但没有发出任何值时,它会切换到另一个可观察对象。
这是两种情况:
- Observable 发出一个值然后完成
- Observable 完成但没有发出值。
诀窍是使用空流作为谓词。
给定一个用作谓词的基本可观察对象,如果您过滤它的发射,您可以将一个 switchIfEmpty 运算符链接到您的后备流。
在下面的代码中 "User" 和 "VIP User" 共享相同的 interface/class。
即使我使用 Java 8 Lambdas 编写代码,请注意没有 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() );
然后我们做一些逻辑,当他是VIP时,我们向下游传递isVip值,如果用户不是VIP,则不会评估flatMap。
Observable<User> vipUser = isVip
// If VIP emit downstream
.filter(vip -> vip)
// This flatmap is ignored if
// the emission is filtered out ( vip -> vip == false )
.flatMap(vip -> user.flatMap(usr -> {
return getVipUserFromNetwork(usr.getId());
}));
});
此时vipUser observable可以
- 发出一个值,即平面化用户
- 不发出任何内容并完成
当什么都没有发出时,switchIfEmpty 将调用另一个 observable
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
});
我是 RXJava/RXAndroid 的新手。我想实现这种情况:根据 RXJava 中的某些条件选择不同的方式。 例如,首先,我从网络中获取用户信息,如果这是 VIP 用户,我将继续从网络中获取更多信息,或者只在主线程中显示一些信息(打破链条。)这里的流程图:https://i.stack.imgur.com/0hztR.png
我对此做了一些搜索,只发现 "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();
有没有更简单的方法来实现这个?
谢谢!
flatMap()
是一个不错的选择,你可以用它拆分流,但最后流合并在一起(每个拆分的可观察到的所有排放都流向主流)。
在您的代码中,switchIfEmpty()
是多余的,因为这正是 Observable.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
}
});
在这种方法中,您只有一个流,流中间没有 'side effects'。
如果你处理的是完全不同的(这不是这种情况),那么你可以将流拆分为 2 个独立的流并对每个流做出不同的反应,这可以通过多播你的 getUserFromNetwork()
可观察,并从这个 Observable
创建 2 个不同的 Observable
,一个将继续,例如 getVipUserFromNetwork()
,一个不会,每个都可以有不同的订阅者逻辑。 (你可以阅读
我最近发现了 switchIfEmpty 运算符,它适合我的需要并且可能对某些人有用。 Rx 对我来说仍然是一种新的思维方式,所以我也愿意接受建议和评论。 让我试着给你另一种思考方式。正如@yosriz 指出的那样,使用 switchIfEmpty 和随后的 onComplete 是多余的。
顾名思义,switchIfEmpty 当基本对象完成但没有发出任何值时,它会切换到另一个可观察对象。
这是两种情况:
- Observable 发出一个值然后完成
- Observable 完成但没有发出值。
诀窍是使用空流作为谓词。
给定一个用作谓词的基本可观察对象,如果您过滤它的发射,您可以将一个 switchIfEmpty 运算符链接到您的后备流。
在下面的代码中 "User" 和 "VIP User" 共享相同的 interface/class。 即使我使用 Java 8 Lambdas 编写代码,请注意没有 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() );
然后我们做一些逻辑,当他是VIP时,我们向下游传递isVip值,如果用户不是VIP,则不会评估flatMap。
Observable<User> vipUser = isVip
// If VIP emit downstream
.filter(vip -> vip)
// This flatmap is ignored if
// the emission is filtered out ( vip -> vip == false )
.flatMap(vip -> user.flatMap(usr -> {
return getVipUserFromNetwork(usr.getId());
}));
});
此时vipUser observable可以
- 发出一个值,即平面化用户
- 不发出任何内容并完成
当什么都没有发出时,switchIfEmpty 将调用另一个 observable
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
});