rxJava。帮助了解如何发布和取消订阅工作

时间:2015-05-15 10:40:33

标签: rx-java

publish()observeOnsubscribeOn结合使用时,我发现了一些奇怪的行为。请看下面的例子。

代码:

ConnectableObservable<String> observable = Observable.create(
    new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            int i=0;
            Log.d("testTag:", "start call");
            while (!subscriber.isUnsubscribed()) {
                subscriber.onNext("item "+i);
                i++;
            }
            Log.d("testTag:", "completed");
            subscriber.onCompleted();
        }
    }
).publish();

observable
    .take(10)
    .subscribe(
        new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d("testTag:", "item received 1 : " + String.valueOf(s));
            }
        });

observable.connect();

输出:

start call
item received 1 : item 0
item received 1 : item 1
item received 1 : item 2
item received 1 : item 3
item received 1 : item 4
item received 1 : item 5
item received 1 : item 6
item received 1 : item 7
item received 1 : item 8
item received 1 : item 9

条件!subscriber.isUnsubscribed()永远不会发生。这完全没问题。添加observeOn(Schedulers.newThread())subscribeOn(Schedulers.newThread())时会发生奇怪的事情。看看:

ConnectableObservable<String> observable = Observable.create(
    new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            int i=0;
            Log.d("testTag:", "start call");
            while (!subscriber.isUnsubscribed()) {
                subscriber.onNext("item "+i);
                i++;
            }
            Log.d("testTag:", "completed");
            subscriber.onCompleted();
        }
    }
)
.observeOn(Schedulers.newThread())
.subscribeOn(Schedulers.newThread())
.publish();

observable
    .take(10)
    .subscribe(
        new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d("testTag:", "item received 1 : " + String.valueOf(s));
            }
        });

observable.connect();

输出:

start call
item received 1 : item 0
item received 1 : item 1
item received 1 : item 2
item received 1 : item 3
item received 1 : item 4
item received 1 : item 5
item received 1 : item 6
item received 1 : item 7
item received 1 : item 8
item received 1 : item 9
completed

请帮助我了解条件!subscriber.isUnsubscribed()成为true的原因。

PS。我了解如果我想检查!subscriber.isUnsubscribed(),我应该使用.publish().refCount()代替connect()。我的目标是了解当前的行为。

1 个答案:

答案 0 :(得分:3)

publish()通过消耗源流直到完成(这里从未发生过)来对0个订阅者做出反应。因此,一旦您使用唯一的subscribe()获取10,源将永远保持运行,或直到您在connect()调用返回的unsubscribe上调用Subscription

在第二种情况下,你得到!subscriber.isUnsubscribed()为true,因为你溢出了observeOn或发布的内部队列,而整个链都以MissingBackpressureException消亡,触发了最终到达你的Observable的取消订阅。

你需要的是share()而不仅仅是publish()所以如果所有订阅者都离开你的源会被终止,但请注意,由于你的Observable不尊重背压,你仍然倾向于{{1} }。

通常,我建议首先查看标准运算符和Observable工厂,而不是滚动Observable,或查看MissingBackpressureException及其javadoc中的示例,以了解如何实现背压感知自定义Observable。