Skip to content

Unexpected behavior of publish() and connect() #2596

@FinalVersion

Description

@FinalVersion

I have experienced some unexpected behaviors of publish() and connect() in my project.
Hopefully it's not my misunderstanding since I'm a newbie to Rx.

I will use an Observer that simply print onNext, onError, onCompleted.

    public static class PrintObserver<T> implements Observer<T> {
        @Override
        public void onCompleted() {
            System.out.println("onCompleted");
        }
        @Override
        public void onError(Throwable e) {
            System.out.println("onError: " + e);
        }
        @Override
        public void onNext(T t) {
            System.out.println("onNext: " + t);
        }
    }

The simplified scenarios are as follows:

  1. ConnectableObservable stops emitting without unsubscribing from source.
    Observable<Integer> source = Observable.range(0, 1000);
    ConnectableObservable<Integer> pub1 = source.publish();
    ConnectableObservable<Integer> pub2 = pub1.publish();
    pub2.connect();
    //pub2.subscribe();
    pub1.subscribe(new PrintObserver<Integer>());
    pub1.connect();

I expected the output to be 'onNext: 0' up to 'onNext: 999', then 'onCompleted', but it stops at onNext: 127 in my test.
But if I uncomment //pub2.subscribe();, namely have something subscribe to pub2, it will work as expected. Or else if I do not pub2.connect(), it will also work.

The code may looks silly, but it may not if I put some operator which does expensive computations before publishing as pub2. BTW, what I want is to do some intermediate computations only once if pub2 is subscribed by many subscribers or piped to different downstream operators. If there're better ways to do that, please kindly let me know.

  1. publish() behaves like replay()
    try {
        Observable<Long> source = Observable.interval(1, TimeUnit.SECONDS).take(10);
        ConnectableObservable<Long> pub = source.publish();
        pub.connect();

        Thread.sleep(2500);

        pub.subscribe(new PrintObserver<Long>());

        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

I expected that after pub.connect(), source will start emitting, and when pub is subscribed after 2.5 sec, 'onNext: 0' and 'onNext: 1' will be missed by this subscriber. However, I got them all together at 2.5 sec, and from 3rd second, I got the following onNext: 2 and so on. This looks like a replay() behavior to me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions