0

I am new to RxJava and if I understand correctly the Observer is passed the Disposable on the onSubscribe so it can manually stop the processing if the dispose() has already been called.
I created the following code:

@NonNull Observable<Long> src = Observable.interval(1, TimeUnit.SECONDS);
src.subscribe(new Observer<Long>() {
      private Disposable d;

      @Override
      public void onSubscribe(@NonNull Disposable d) {
           this.d = d;
      }

      @Override
      public void onNext(@NonNull Long aLong) {
           if(!d.isDisposed()) {
              System.out.println("Number onNext = " + aLong);
           }
      }

       @Override
       public void onError(@NonNull Throwable e) {

       }

       @Override
       public void onComplete() {
           System.out.println("completed");
       }
 });

but I can't figure out how to call dispose() for that subscription. subscribe with passing Observer as an argument returns void and subscribeWith does not accept my Observer without compile errors.

How is this supposed to work? What am I misunderstanding here?

Jim
  • 3,845
  • 3
  • 22
  • 47

2 Answers2

1

The JavaDocs of Observable has a straightforward example:

Disposable d = Observable.just("Hello world!")
     .delay(1, TimeUnit.SECONDS)
     .subscribeWith(new DisposableObserver<String>() {
         @Override public void onStart() {
             System.out.println("Start!");
         }
         @Override public void onNext(String t) {
             System.out.println(t);
         }
         @Override public void onError(Throwable t) {
             t.printStackTrace();
         }
         @Override public void onComplete() {
             System.out.println("Done!");
         }
     });

 Thread.sleep(500);
 // the sequence can now be disposed via dispose()
 d.dispose();

Edit

The following examples are ways to get the Disposable out of the onSubscribe method but are generally not recommended:

// field in the owner class
Disposable disposable;

public void doReactive() {
    Observable<Long> src = Observable.interval(1, TimeUnit.SECONDS);
    src.subscribe(new Observer<Long>() {

        @Override
        public void onSubscribe(@NonNull Disposable d) {
           disposable = d;
        }

        // ...
    });
}

public void cleanup() {
   if (disposable != null) {
       disposable.dispose();
       disposable = null;
   }
}

or

SerialDisposable sd = new SerialDisposable();

Observable<Long> src = Observable.interval(1, TimeUnit.SECONDS);
    src.subscribe(new Observer<Long>() {

        @Override
        public void onSubscribe(@NonNull Disposable d) {
           sd.set(d);
        }

        // ...
    });

// ...

sd.dispose();
akarnokd
  • 69,132
  • 14
  • 157
  • 192
  • So then why is the `Disposable` passed as argument on the `onSubscribe` of the `Observer` if I can't do anything with it? – Jim Jun 15 '21 at 16:23
  • It has advanced usages such as implementing operators. For an end-consumer, you are better off with `DisposableObserver` or one of the lambda-subscribe methods. – akarnokd Jun 15 '21 at 19:02
  • And when would I use `DisposableObserver` with `subscribe`? I see you use `subscribeWith` which returns the disposable but `subscribe` returns `void` – Jim Jun 15 '21 at 20:44
  • You can `new` up the `DisposableObserver` upfront, assign it to a local variable and hand it to the `subscribe` method too. – akarnokd Jun 16 '21 at 06:34
  • But what is the difference with `subscribeWith`? Is it just a more convenient method to avoid doing what you decribed? Because even if I keep the local reference I would not be able to do `dispose()` – Jim Jun 16 '21 at 07:35
  • `subscribeWith` returns its input parameter, `subscribe` does not. The former is a [convenience](https://github.com/ReactiveX/RxJava/blob/3.x/src/main/java/io/reactivex/rxjava3/core/Observable.java#L13183-L13186) over the latter. You'd have to put that `Disposable` of `onSubscribe` somewhere that is accessible from outside. – akarnokd Jun 16 '21 at 08:44
  • Your answers helps a lot! Thank you very much! – Jim Jun 16 '21 at 09:34
0

You can use the DisposableObserver which can be easily disposed when you are done observing.

@NonNull Observable<Long> src = Observable.interval(1, TimeUnit.SECONDS);
    src.subscribe(new DisposableObserver<Long>() {
        @Override
        public void onNext(@NotNull Long aLong) {
            //Do anything you want to do..
            dispose();
        }

        @Override
        public void onError(@NotNull Throwable e) {
            //Handle the errors here..
            dispose();
        }

        @Override
        public void onComplete() {
            dispose();
        }
    });

You can also use CompositeDisposable to dispose many observers at one time, For more details check this out.

https://www.tutorialspoint.com/rxjava/rxjava_compositedisposable.htm