如何在RxJava中拥有多个订阅者到一个分组的Observable?

时间:2014-08-19 01:29:50

标签: java system.reactive rx-java

这是使用RxJava版本 0.19.6

在groupBy操作之外,可以创建由以下代码描述的管道,例如,根据某些条件从Observable中选择记录,或者选择满足某些备用条件的第一条记录:

Observable<Long> observable = Observable.interval(1, TimeUnit.MILLISECONDS).take(10);
Observable<Long> filter1 = observable.filter(new Func1<Long, Boolean>() {
    @Override
    public Boolean call(Long aLong) {
        return 5 == aLong % 5;
    }
});
Observable<Long> filter2 = observable.filter(new Func1<Long, Boolean>() {
    @Override
    public Boolean call(Long aLong) {
        return 2 == aLong % 5;
    }
});
BlockingObservable.from(Observable.concat(filter1, filter2).first()).forEach(new Action1<Long>() {
    @Override
    public void call(Long aLong) {
        System.out.println(aLong);
    }
});

...遗憾的是,由于对GroupedObservable的限制,似乎同一类程序无法在分组上下文中运行:

BlockingObservable.from(observable.groupBy(new Func1<Long, Long>() {
    @Override
    public Long call(Long aLong) {
        return aLong % 5;
    }
}).flatMap(new Func1<GroupedObservable<Long, Long>, Observable<Long>>() {
    @Override
    public Observable<Long> call(GroupedObservable<Long, Long> in) {
        Observable<Long> filter1 = in.filter(new Func1<Long, Boolean>() {
            @Override
            public Boolean call(Long aLong) {
                return 5 == aLong % 5;
            }
        });
        Observable<Long> filter2 = in.filter(new Func1<Long, Boolean>() {
            @Override
            public Boolean call(Long aLong) {
                return 2 == aLong % 5;
            }
        });
        return Observable.concat(filter1, filter2).first();
    }
})).forEach(new Action1<Long>() {
    @Override
    public void call(Long aLong) {
        System.out.println(aLong);
    }
});

...导致多个订阅者异常(线程中的异常&#34; main&#34; java.lang.IllegalStateException:只允许一个订阅者!)。

我错过了一些明显的解决方法吗?在这种情况下,我尝试使用ConnectableObservables来提供单个订阅服务器的外观,但这些尝试也是失败的(当然是由于我的无知)。


在一个相关的说明中,groupByUntil似乎也提供了对GroupedObservable的引用,如果我真的试图用它来确定何时关闭窗口,这给我带来了类似的抱怨多个订阅者的头痛。在这里我再次确定我忽略了一些显而易见的事情,因为API显然希望人们使用GroupedObservable!

3 个答案:

答案 0 :(得分:0)

您可以在GroupedObservable上使用.cache()。

final Observable<Long> inCached = in.cache();

然后在过滤器中使用生成的Observable。

Observable<Long> filter1 = inCached.filter(new Func1<Long, Boolean>() {
        @Override
        public Boolean call(Long aLong) {
            return 5 == aLong % 5;
        }
    });

这样每个订阅者都会看到相同的项目,但GroupedObservable只有一个订阅者。

答案 1 :(得分:0)

您可以将过滤器组合到单个过滤器中:

Observable<Long> observable = Observable.interval(1, TimeUnit.MILLISECONDS).take(10);
BlockingObservable.from(observable.groupBy(new Func1<Long, Long>() {
    @Override
    public Long call(Long aLong) {
        return aLong % 5;
    }
}).flatMap(new Func1<GroupedObservable<Long, Long>, Observable<Long>>() {
    @Override
    public Observable<Long> call(GroupedObservable<Long, Long> in) {
        Observable<Long> filter = in.filter(new Func1<Long, Boolean>() {
            @Override
            public Boolean call(Long aLong) {
                return 2 == aLong % 5 || 4 == aLong % 5;
            }
        });
        return filter;
    }
})).forEach(new Action1<Long>() {
    @Override
    public void call(Long aLong) {
        System.out.println(aLong);
    }
});

答案 2 :(得分:-1)

您是否尝试过升级rxJava版本?

https://github.com/ReactiveX/RxJava/issues/957