在subscribeOn之后不起作用

时间:2017-05-03 07:13:19

标签: rx-java

使用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

1 个答案:

答案 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();