RxJava:了解简单异步操作之间的区别

时间:2017-11-21 06:32:26

标签: android rx-java

我正在学习RxJava并遇到一个看似微不足道的问题,我确信这只是我对RxJava如何工作的误解。我在下面有两个代码块,演示了一个简单的ObservableConsumer对,其中Observable发出一个从1到4的整数计数流,每个都有一秒钟的延迟。

代码段A - 导致用户界面冻结

Observable<Integer> observable = Observable.create(e -> {
    e.onNext(1);
    Thread.sleep(1000);
    e.onNext(2);
    Thread.sleep(1000);
    e.onNext(3);
    Thread.sleep(1000);
    e.onNext(4);
    Thread.sleep(1000);
    e.onComplete();
});
observable.subscribeOn(Schedulers.io());
observable.observeOn(AndroidSchedulers.mainThread());
observable.subscribe(i -> Log.e(TAG, "onNext: " + i));

代码段B - 行为正确

Observable.create(e -> {
    e.onNext(1);
    Thread.sleep(1000);
    e.onNext(2);
    Thread.sleep(1000);
    e.onNext(3);
    Thread.sleep(1000);
    e.onNext(4);
    Thread.sleep(1000);
    e.onComplete();
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(i -> Log.e(TAG, "onNext: " + i));

我不明白的问题是为什么Snippet A会冻结我的UI,但Snippet B的工作方式与预期一致并在后台运行。此代码从onClick中的Button运行,我可以告诉Snippet A导致UI冻结,因为在片段B完全正常运行时,波纹动画停止。

问题:创建Observable的实例/指针和使用构建器范例初始化Observable之间有什么区别?为什么上面的两个代码片段在实践中有所不同?

1 个答案:

答案 0 :(得分:2)

这是因为名为操作员链接的概念。每个运算符都将返回一个具有其效果的observable,您需要订阅上一步返回的新observable以查看效果

SnippetA将成为

Observable<Integer> observable = Observable.create(e -> {
    e.onNext(1);
    Thread.sleep(1000);
    e.onNext(2);
    Thread.sleep(1000);
    e.onNext(3);
    Thread.sleep(1000);
    e.onNext(4);
    Thread.sleep(1000);
    e.onComplete();
});
Observable ioSubscription = observable.subscribeOn(Schedulers.io());
Observable mainThreadObservable = ioSubscription.observeOn(AndroidSchedulers.mainThread());
mainThreadObservable.subscribe(i -> Log.e(TAG, "onNext: " + i));

链接运算符

大多数操作符在Observable上操作并返回Observable。这允许您在链中一个接一个地应用这些运算符。链中的每个运算符都会修改由前一个运算符的运算产生的Observable。

还有其他模式,如Builder模式,其中特定类的各种方法通过方法的操作修改该对象,对同一类的项进行操作。这些模式还允许您以类似的方式链接方法。但是在Builder模式中,方法在链中出现的顺序通常并不重要,Observable运算符的顺序很重要。

一组Observable运算符不能在原始的Observable上独立运行,它发起链,但是它们依次运行,每个运算符都由运算符在链中的前一个运算符生成。

参考:Observable