在某些情况下,我需要建立一个由多个元素组成的反应性流,可以用两种不同的方式来完成。
我的链条看起来像这样:
在链的顶部,我有多个Flowable
生产者,每个生产者定期轮询不同的远程资源并在获得新结果时发出消息。
每个生产者都有一个中间订户,可以进一步转换消息。
依次,所有这些中间订阅者都具有相同的根订阅者,该根订阅者将来自所有人的转换后的事件合并为一个Flowable
我想要的是能够取消根订阅者的任何订阅,并让取消订阅事件基本上导致取消订阅(这是一个单词吗?)。
换句话说,如果没有人在听,我希望我的轮询过程停止。如果我需要重新启动轮询,只需重建一个新链。
是否有任何RxJava运算符允许我在生产者和订阅者之间创建这种关系?如果没有,那么最简单的方法是什么?
我现在有一种解决方案,但是感觉不是一个很好的解决方案,并且链中每个元素都需要大量样板代码。看起来像这样:
private class AutoUnsubscribing {
private final AtomicReference<Subscription> upstreamSubscription = new AtomicReference<>(null);
private final PublishProcessor<LedgerEvent> publisher = PublishProcessor.create();
public Flowable<LedgerEvent> getFlowable(Flowable<LedgerEvent> upstream) {
upstream.subscribe(new Subscriber<LedgerEvent>() {
@Override
public void onSubscribe(Subscription s) {
upstreamSubscription.set(s);
}
@Override
public void onNext(LedgerEvent ledgerEvent) {
publisher.onNext(ledgerEvent);
}
@Override
public void onError(Throwable t) {
publisher.onError(t);
}
@Override
public void onComplete() {
publisher.onComplete();
}
});
return publisher.doOnCancel(() -> {
if (!publisher.hasSubscribers()) {
// no more subscribers. unsubscribe from upstream and complete this stream
upstreamSubscription.get().cancel();
upstreamSubscription.set(null);
publisher.onComplete();
}
});
}
}
但是必须有比这更好的解决方案。
答案 0 :(得分:0)
现在,我已经在RxJava方面获得了更多的经验,现在可以为我的问题提出答案。基本上,我们拥有的链条如下:
+----------+ +-------------+ +----------+ | consumer |←-----| transformer |←-----| producer | +----------+ +-------------+ +----------+
真正需要的是一种使transformer
可取消的方法,以使取消该预订时取消对producer
的订阅(因此producer
可以进行一些清理)在终止自身之前),并且AND transformer
完成自身(以便consumer
意识到这一点)。
我能找到的最佳解决方案是像这样实现detachable
运算符:
public static <T> FlowableTransformer<T, T> detachable(
Consumer<Disposable> disposableConsumer) {
PublishProcessor<Object> stopper = PublishProcessor.create();
Disposable disposable = new Disposable() {
private AtomicBoolean disposed = new AtomicBoolean(false);
@Override
public void dispose() {
if (disposed.compareAndSet(false, true)) {
stopper.onNext(new Object());
}
}
@Override
public boolean isDisposed() {
return disposed.get();
}
};
return upstream -> upstream.takeUntil(stopper)
.doOnSubscribe(s -> disposableConsumer.accept(disposable));
}
然后可以使用哪种方式:
AtomicReference<Disposable> transformerDisposable = new AtomicReference<>();
producer
.compose(detachable(transformerDisposable::set))
.subscriber(consumer)
然后可以使用{p>随意取消transfomer
transformerDisposable.dispose()
这确实会导致producer
调用自己的onUnsubscribe
,并且consumer
会收到onComplete
通知。