我想知道从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
发生时,没有更多的东西可以写入输出,所以我需要以某种方式停止进一步处理。)
答案 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));