RxJava:在onNext中调用取消订阅

时间:2015-06-24 12:51:25

标签: java rx-java

我想知道从unsubscribe处理程序中调用onNext是否合法:

List<Integer> gatheredItems = new ArrayList<>();

Subscriber<Integer> subscriber = new Subscriber<Integer>() {
    public void onNext(Integer item) {
        gatheredItems.add(item);
        if (item == 3) {
            unsubscribe();
        }
    }
    public void onCompleted() {
        // noop
    }
    public void onError(Throwable sourceError) {
        // noop
    }
};

Observable<Integer> source = Observable.range(0,100);

source.subscribe(subscriber);
sleep(1000);
System.out.println(gatheredItems);

上面的代码正确输出只收集了四个元素:[0, 1, 2, 3]。但是如果有人将源可观察性更改为缓存:

Observable<Integer> source = Observable.range(0,100).cache();

然后收集所有一百个元素。我没有对source observable的控制(无论是否缓存),那么如何在onNext内明确取消订阅?

顺便说一句:那么在onNext错误的事情中取消订阅是什么意思?

(我的实际用例是onNext我实际上正在写输出流,当IOException发生时,没有更多的东西可以写入输出,所以我需要以某种方式停止进一步处理。)

1 个答案:

答案 0 :(得分:3)

一旦第一个订户到达,cache()就会缓存所有内容,并且它没有提供任何阻止它从下游停止的选项。您需要在缓存()之前停止流以避免过多保留:

Observable<Integer> source = Observable.range(1, 100);

PublishSubject<Integer> stop = PublishSubject.create();

source
.doOnNext(v -> System.out.println("Generating " + v))
.takeUntil(stop)
.cache()
.doOnNext(new Action1<Integer>() {
    int calls;
    @Override
    public void call(Integer t) {
        System.out.println("Saving " + t);
        if (++calls == 3) {
            stop.onNext(1);
        }
    }
})
.subscribe();

编辑:上面的示例在1.0.13以下不起作用,所以这里应该是一个版本:

SerialSubscription ssub = new SerialSubscription();

ConnectableObservable<Integer> co = source
        .doOnNext(v -> System.out.println("Generating " + v))
        .replay();

co.doOnNext(v -> {
    System.out.println("Saving " + v);
    if (v == 3) {
        ssub.unsubscribe();
    }
})
.subscribe();

co.connect(v -> ssub.set(v));