Java Observable.publish()不';t在源可观察对象完成后,对订阅的观察者调用onCompleted()

Java Observable.publish()不';t在源可观察对象完成后,对订阅的观察者调用onCompleted(),java,rx-java,reactive-programming,Java,Rx Java,Reactive Programming,我试图让一个可观测的与所有订户共享它的排放量,这样它就可以被订阅一次。 我尝试使用Observable.publish(),但是如果发布的Observable的订阅者在源Observable完成后订阅,他们似乎不会收到任何终止消息(onCompleted(),可能还会收到onError())。下面是一段代码来演示: static <T> Observer<T> printObserver(String name) { return new Observer<

我试图让一个
可观测的
与所有订户共享它的排放量,这样它就可以被订阅一次。
我尝试使用
Observable.publish()
,但是如果发布的
Observable
的订阅者在源
Observable
完成后订阅,他们似乎不会收到任何终止消息(
onCompleted()
,可能还会收到
onError()
)。下面是一段代码来演示:

static <T> Observer<T> printObserver(String name) {
    return new Observer<T>() {
        @Override public void onCompleted() {
            System.out.println(name + ": onCompleted()");
        }
        @Override public void onError(Throwable e) {
            System.out.println(name + ": onError( " + e + " )");
        }
        @Override public void onNext(T value) {
            System.out.println(name + ": onNext( " + value + " )");
        }
    };
}
public void testRxPublishConnect() throws Exception {
    Observable<Integer> sourceObservable = Observable.range(1, 5);
    ConnectableObservable<Integer> sharedObservable = sourceObservable.publish();
    sharedObservable.subscribe(printObserver("Observer #1"));
    sharedObservable.connect();
    sharedObservable.subscribe(printObserver("Observer #2"));
}
静态观察者printObserver(字符串名称){
返回新的观察者(){
@覆盖已完成的公共void(){
System.out.println(name+“:onCompleted()”;
}
@覆盖公共无效onError(可丢弃的e){
System.out.println(名称+”:onError(“+e+”);
}
@覆盖公共void onNext(T值){
System.out.println(名称+”:onNext(“+value+”);
}
};
}
public void testRxPublishConnect()引发异常{
可观测源可观测=可观测范围(1,5);
ConnectableObservable sharedObservable=sourceObservable.publish();
sharedObservable.subscribe(printObserver(“Observer#1”));
sharedObservable.connect();
sharedObservable.subscribe(printObserver(“Observer#2”));
}
这就是要打印的内容:

Observer #1: onNext( 1 ) Observer #1: onNext( 2 ) Observer #1: onNext( 3 ) Observer #1: onNext( 4 ) Observer #1: onNext( 5 ) Observer #1: onCompleted() 观察员#1:onNext(1) 观察员#1:onNext(2) 观察员#1:onNext(3) 观察员#1:onNext(4) 观察员#1:onNext(5) 观察员1:未完成() 请注意,
Observer#2
不接收
onCompleted()。
我认为这不是我想要的行为。我错过什么了吗?

我在RxJava版本1.0.8和1.0.14中尝试了它,得到了相同的结果。

我99%确信这是预期的行为。我不确定RxJava,但在我所知道的发布和订阅模式的大多数实现中,可观察对象的默认行为是将事件发布给订阅者,然后忘记它们。这意味着通知不是“追溯活动”(即订阅者不了解过去发出的事件的任何信息)

此外,从:


如果第二个观察者订阅了一个已经向第一个观察者发射项目的可观察者,则由该可观察者决定是否从此向每个观察者发射相同的项目。。。一般来说,无法保证两个具有相同观察对象的观察者将看到相同的项目序列

尝试
.share()
,即
.publish().refCount()

通过构建所有订阅者的列表,然后一次
connect()
被称为,它开始向其订户列表中的所有订户生成数据。这意味着在调用connect之前必须知道所有订户。下面是如何使用
publish()
或更可取的
publish(Func1)
重载

已知订阅服务器数:发布

Func关闭所有订阅

observeStream.publish(新函数1(){
@凌驾
公共可观察呼叫(可观察主体){
o1=subject.doOnNext(somework1());
可观察o2=受试者.doOnNext(somework2());
可观察的返回。合并(o1,o2);
}
});
手动呼叫以连接和订阅:

ConnectableObservable subject=observableStream.publish();
subject.subscribe(somework1());
subject.subscribe(somework2());
subject.connect();
如果您不知道您将拥有多少订阅者,那么您可以将输入窗口化为可管理的块,然后通过
Transformer
s的集合发布您的输入

订阅服务器数未知:Windows

final Set transformers=new HashSet();
可见光
.窗口(100,TimeUnit.ms,1000)
.flatMap(新函数1(){
@凌驾
公共可观察呼叫(可观察窗口){
返回window.publish(新函数1(){
@凌驾
公共可观测呼叫(可观测发布){
可观测的工作可观测=可观测。来自(变压器)
.map(新函数1(){
@凌驾
公共可观察呼叫(变压器){
返回publish.compose(transformer);
}});
返回可观测。合并(可观测);
}});
}})
.subscribe();

还有第三种选择。您可以使用
observable.cache()
,但这将在内存中保存来自该可观察流的所有输入数据,因此您需要注意如何使用它。在这种情况下,您可能最终会打开窗口来控制缓存主题的边界

这是设计的。如果在这种情况下调用
connect()
,您的订户将从一开始就接收所有事件。如果终止的
publish
会立即终止其子订阅服务器,则可能无法观察值,因为一旦连接,
publish
如果没有订阅服务器,则会缓慢地勾选其源。

onNext()通知也是如此。就我所知,onError()和onCompleted()通知并非如此。为了确保这一点,我检查了PublishSubject,它总是向订阅者提供onCompleted()通知,即使onCompleted()早就被调用了。这是我的第一种方法。问题是,在所有订阅者取消订阅后(或在源Observable完成后,它自动取消订阅所有订阅者)和新订阅者订阅后,源Observable将再次被订阅。更清楚的是,使用PublishSubject解决了我的问题。我只是觉得.publish()的行为很奇怪。好吧,请原谅我没有完整地阅读你的问题,我只是在一分钟内就把这个抛了出去