RxJava:subscribeOn和observeOn未按预期工作
也许我只是真正理解了RxJava:subscribeOn和observeOn未按预期工作,java,rx-java,reactivex,Java,Rx Java,Reactivex,也许我只是真正理解了subscribeOn和observeOn的内部工作原理,但我最近遇到了一些非常奇怪的事情。我的印象是,subscribeOn决定了调度器最初开始处理的位置(特别是当我们有很多maps改变数据流时),然后observeOn可以在这些map之间的任何地方使用,在适当的时候改变调度器(先联网,然后计算,最后更改UI线程) 但是,我注意到,如果不将这些调用直接链接到我的Observable或Single,它将无法工作。下面是一个JUnit测试的最小工作示例: import org.
subscribeOn
和observeOn
的内部工作原理,但我最近遇到了一些非常奇怪的事情。我的印象是,subscribeOn
决定了调度器最初开始处理的位置(特别是当我们有很多map
s改变数据流时),然后observeOn
可以在这些map
之间的任何地方使用,在适当的时候改变调度器(先联网,然后计算,最后更改UI线程)
但是,我注意到,如果不将这些调用直接链接到我的Observable或Single,它将无法工作。下面是一个JUnit测试的最小工作示例:
import org.junit.Test;
import rx.Single;
import rx.schedulers.Schedulers;
public class SubscribeOnTest {
@Test public void not_working_as_expected() throws Exception {
Single<Integer> single = Single.<Integer>create(singleSubscriber -> {
System.out.println("Doing some computation on thread " + Thread.currentThread().getName());
int i = 1;
singleSubscriber.onSuccess(i);
});
single.subscribeOn(Schedulers.computation()).observeOn(Schedulers.io());
single.subscribe(integer -> {
System.out.println("Observing on thread " + Thread.currentThread().getName());
});
System.out.println("Doing test on thread " + Thread.currentThread().getName());
Thread.sleep(1000);
}
@Test public void working_as_expected() throws Exception {
Single<Integer> single = Single.<Integer>create(singleSubscriber -> {
System.out.println("Doing some computation on thread " + Thread.currentThread().getName());
int i = 1;
singleSubscriber.onSuccess(i);
}).subscribeOn(Schedulers.computation()).observeOn(Schedulers.io());
single.subscribe(integer -> {
System.out.println("Observing on thread " + Thread.currentThread().getName());
});
System.out.println("Doing test on thread " + Thread.currentThread().getName());
Thread.sleep(1000);
}
}
而按预期工作()
给了我
Doing some computation on thread RxComputationScheduler-1
Doing test on thread main
Observing on thread RxIoScheduler-2
唯一的区别是,在第一次测试中,在创建单之后,有一个分号,然后才应用调度程序,在工作示例中,方法调用直接链接到单的创建。但这难道不应该是无关的吗?所有“修改”运算符执行的操作是不可变的,这意味着它们返回一个新的流,该流以与前一个流不同的方式接收通知。由于您刚刚调用了subscribeOn
和observeOn
运算符,并且没有存储它们的结果,因此以后进行的订阅位于未更改的流上
一方面注意:我不太理解您对
subscribeOn
行为的定义。如果您是说映射运算符受到它的影响,那就不是这样了。subscribeOn
定义了一个调度程序,在该调度程序上调用OnSubscribe函数。在您的例子中,传递给create()的函数
方法。另一方面,observeOn
定义了每个连续流(由应用的操作员返回的流)处理来自上游的排放的调度程序。.subscribeOn(*)
-返回可观察的新实例,但在第一次测试中,您只需忽略该实例,然后订阅原始的可观察的实例,这显然是默认情况下订阅的主线程。这是一个非常常见的错误。每个操作符返回一个新对象,您应该进一步链接。您只需应用subscribeOn+observeOn,忽略返回的单条并订阅原始未更改的源。
Doing some computation on thread RxComputationScheduler-1
Doing test on thread main
Observing on thread RxIoScheduler-2