3

Given a cold example:

Observable<Integer> cold = Observable.create(subscriber -> {
  try {
    for (int i = 0; i <= 42; i++) {

      // avoid doing unnecessary work
      if (!subscriber.isUnsubscribed()) {
        break;
      }

      subscriber.onNext(i);
    }
    subscriber.onCompleted();
  } catch (Throwable cause) {
    subscriber.onError(cause);
  }
});

it starts executing from scratch for every new subscriber :

// starts execution
cold.subscribe(...)

and can stop execution if subscriber unsubscribes early :

// stops execution
subscription.unsubscribe();

now if instead of the sample for loop we have some actual business logic going on (which does not need to replay for each subscriber but be realtime instead) then we are dealing with hot observable...

PublishSubject<Integer> hot = PublishSubject.create();

Thread thread = new Thread(() -> {
  try {
    for (int i = 0; i < 42; i++) {
      // how to avoid unnecessary work when no one is subscribed?
      hot.onNext(i);
    }
    hot.onCompleted();
  } catch (Throwable cause) {
    hot.onError(cause);
  }
});

when we want it to start we might do

// stats work (although no one is subscribed) 
thread.start();

hence the first question : how to start work only when first observer subscribes? (connectable observable maybe?)

and the important question : how to stop work when last subscriber unsubscribes? (I cant figure out how to access current subscriptions for that subject, and would like to find clean solution without shared global state if such solution exists)

One solution i can think of is to lift subject with custom operator which will manage subscribers...

vach
  • 10,571
  • 12
  • 68
  • 106

1 Answers1

4

see operator refCount - http://reactivex.io/documentation/operators/refcount.html. This Operator turns your Observable into ConnectableObservable, and connects it when first subscriber subscribes, and disconnects when there are no more subscriptions

krp
  • 2,247
  • 17
  • 14