我正在学习RxJava并遇到一个看似微不足道的问题,我确信这只是我对RxJava如何工作的误解。我在下面有两个代码块,演示了一个简单的Observable
和Consumer
对,其中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
之间有什么区别?为什么上面的两个代码片段在实践中有所不同?
答案 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