使用subscribeOn
排除
PublishSubject<Void> repeatSubject = PublishSubject.create();
Observable.
<Integer>create(subscriber -> {
System.out.println("1");
subscriber.onNext(1);
subscriber.onCompleted();
}).
//subscribeOn(Schedulers.computation()).
repeatWhen(h -> h.flatMap(nothing -> repeatSubject)).
subscribe();
repeatSubject.onNext(null);
按预期打印两个'1'。
但是,只有我取消注释subscribeOn
,才会打印出唯一的 one'1'。必须repeatWhen
不会重新订阅可观察对象。为什么呢?
P.S。感谢 yosriz 提供了很好的解释。所以现在问题不是'为什么',而是'如何'。我怎么能从主线程中重复在另一个线程上安排的observable呢?
P.P.S。以下修改仍然打印一个'1'。
BehaviorSubject<Void> repeatSubject = BehaviorSubject.create();
Observable.
<Integer>create(subscriber -> {
System.out.println("1");
subscriber.onNext(1);
subscriber.onCompleted();
})
.subscribeOn(Schedulers.computation())
.repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
@Override
public Observable<?> call(Observable<? extends Void> observable) {
return observable.zipWith(repeatSubject, new Func2<Void, Void, Object>() { // called on main thread
@Override
public Object call(Void aVoid, Void aVoid2) {
return new Object(); // never called !
}
});
}
})
.subscribe();
repeatSubject.onNext(null); // called on main thread
答案 0 :(得分:2)
那是因为在第一种情况下,当你没有指定Scheduler
时,订阅会立即以阻塞的方式发生在这个线程上,所以当repeatWhen
订阅了repeatSubject
时{1}},它还没有发射。所以flatMap
在您致电repeatSubject.onNext(null);
之前就已发生了
这意味着,首先,flatMap
订阅了repeatSubject
,然后onNext(null)
被调用,repeatWhen
重新订阅了源Observable
。
当您指定调度程序时,所有Observable
序列都在一个单独的线程上进行了调度,因此repeatSubject.onNext(null);
可能在flatMap
订阅之前发生repeatSubject,(你不能保证两个操作在两个不同的线程中发生),所以它错过了通知,因此重复没有工作。
您可以通过添加日志来观察行为:
Observable.
<Integer>create(subscriber -> {
System.out.println("1");
subscriber.onNext(1);
subscriber.onCompleted();
}).
subscribeOn(Schedulers.computation()).
repeatWhen(h -> h.flatMap(nothing -> {
System.out.println("repeatWhen flatMap");
return repeatSubject;
})).
subscribe();
System.out.println("repeatSubject.onNext");
repeatSubject.onNext(null);
修改强>
如何重复:
您可以使用zip
将完成的排放和Subject.onNext()
排放同步到一起,这样,每个onNext()
将重复单次重复序列:
Observable.
<Integer>create(subscriber -> {
System.out.println("1");
subscriber.onNext(1);
subscriber.onCompleted();
})
.subscribeOn(Schedulers.computation())
.repeatWhen(completeNotfications ->
completeNotfications.zipWith(repeatSubject, (o, aVoid) -> new Object()))
.subscribe();