我们假设我有以下Android案例:
我想使用RxJava执行此操作:
webService.requestGroups()
.flatMap(group -> {
view.showGroup(group);
return webService.requestItems(group);
})
.toList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> view.showItems(items));
正如您所看到的,我有2个视图对象调用,每个调用都必须在主线程上执行。并且2次调用webService,必须在后台线程上执行。
此代码的问题:第一次调用视图将在后台执行导致Android RuntimeException(只有原始线程可能会触及视图或其他内容)如果我将.observeOn
转移到链的开头 - 第二次webService调用将在主线程中执行。
我怎样才能游泳"在RxJava链中多次通过线程?
答案 0 :(得分:13)
SubscribeOn运算符指定Observable将开始运行的线程,无论运算符链中的哪个运算符被调用。另一方面,ObserveOn会影响Observable将在该运算符出现的位置下方使用的线程。因此,您可以在Observable运算符链中的不同点多次调用ObserveOn,以便更改某些运算符在哪些线程上运行。
SubscribeOn运算符只能应用一次并设置起始线程。 ObserveOn可用于在流中的任何位置从一个线程转到另一个线程。所以我认为以下应该做你想做的事情:
webService.requestGroups()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(group -> {
view.showGroup(group);
return webService.requestItems(group)
.subscribeOn(Schedulers.io());
})
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> view.showItems(items));
但在我看来,这太复杂了。我只想订阅第一个observable,然后为每个组启动一个新链,如下所示:
webService.requestGroups()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(group -> {
view.showGroup(group);
webService.requestItems(group)
.subscribeOn(Schedulers.io()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> view.showItems(items));
});
答案 1 :(得分:2)
基于塞缪尔(Samuel)的答案,您可以使用更简单,非嵌套的语法来做到这一点:
webService.requestGroups()
.subscribeOn(Schedulers.io()) // the first operator (requestGroups) on the IO thread
.observeOn(AndroidSchedulers.mainThread()) //everything below on the main thread
.map(group -> {
view.showGroup(group);
return group;
})
.observeOn(Schedulers.io()) //everything below on the IO thread
.flatMap(group -> {
return webService.requestItems(group);
})
.toList()
.observeOn(AndroidSchedulers.mainThread()) //everything below on the main thread
.subscribe(items -> view.showItems(items));
这里有两个经验法则:
subscribeOn
指示可观察对象将在哪个线程上开始执行,它在链中的位置无关紧要,并且应该只出现一次。observeOn
告诉所有后续运算符将在哪个线程上执行(直到遇到另一个observeOn
为止);它可能在链中出现多次,从而改变了不同代码段的执行线程(如上例所示)。