我有一个长时间运行的任务(比如一个Observable<Integer>
)我想在我的应用程序中尽可能少地触发。我有多个&#34;观点&#34;处理以各种方式发送的事件的任务。我的整个应用程序中只有一个subscribe
。
如何确保长时间运行的任务仅针对每个订阅触发一次,并且仅在订阅需要时触发?
为了使事情更具体,这是一个单元测试:
@Test
public void testSubscriptionCount() {
final Counter counter = new Counter();
// Some long running tasks that should be triggered once per subscribe
final Observable<Integer> a = Observable.just(1, 2, 3, 4, 5)
.doOnSubscribe(subscription -> {
counter.increment();
});
// Some "view" on the long running task
final Observable<Integer> b = a.filter(x -> x % 2 == 0);
// Another "view" on the long running task
final Observable<Integer> c = a.filter(x -> x % 2 == 1);
// A view on the views
final Observable<Integer> d = Observable.zip(b, c, (x, y) -> x + y);
d.toList().blockingGet();
assertEquals(1, counter.count); // Fails, counter.count == 2
}
我希望a
只能在订阅其中一个视图(b
,c
或d
)时触发,而且每个订阅只能触发一次。
在上面的代码中,订阅发生两次(我假设d
触发b
和c
,它们都独立触发a
。
添加.share()
并不能解决问题(尽管我认为这是正确的):
// Some long running tasks that should be triggered once per subscribe
final Observable<Integer> a = Observable.just(1, 2, 3, 4, 5)
.doOnSubscribe(subscription -> counter.increment())
.share();
java.lang.AssertionError:
预计:1
实际:2
答案 0 :(得分:0)
如果您的目标是在观察者并行订阅时阻止多次执行,Observable<Integer> shared = source.share();
// In thread 1:
shared.subscribe(...);
// In thread 2:
shared.subscribe(...);
就是您所寻找的:
.share()
只要源observable在第二次订阅发生时尚未完成,它将获得与第一次订阅相同的结果,并且不会强制执行源可观察的另一次。
RxJava文档有更详细的解释,但它基本上是一个包含一些引用计数的包装器,并且只在必要时订阅源observable以避免并发执行。
还要记住,时间安排将在实际传递价值的过程中起到重要作用。我不相信.buffer()
将对元素进行任何特定的缓冲,因此如果元素在第二个订阅之前传递,则第二个订阅将不会获得这些元素。您必须使用HEAD
或其他一些方法来保留后期订阅者的结果。