diff --git a/src/main/java/io/reactivex/observers/DefaultObserver.java b/src/main/java/io/reactivex/observers/DefaultObserver.java index ec79fb41e6..096388c2e9 100644 --- a/src/main/java/io/reactivex/observers/DefaultObserver.java +++ b/src/main/java/io/reactivex/observers/DefaultObserver.java @@ -18,10 +18,48 @@ import io.reactivex.internal.disposables.DisposableHelper; /** - * Abstract base implementation of an Observer with support for cancelling a + * Abstract base implementation of an {@link io.reactivex.Observer Observer} with support for cancelling a * subscription via {@link #cancel()} (synchronously) and calls {@link #onStart()} * when the subscription happens. * + *
All pre-implemented final methods are thread-safe. + * + *
Use the protected {@link #cancel()} to dispose the sequence from within an + * {@code onNext} implementation. + * + *
Like all other consumers, {@code DefaultObserver} can be subscribed only once. + * Any subsequent attempt to subscribe it to a new source will yield an + * {@link IllegalStateException} with message {@code "Disposable already set!"}. + * + *
Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)} + * and {@link #onComplete()} are not allowed to throw any unchecked exceptions. + * If for some reason this can't be avoided, use {@link io.reactivex.Observable#safeSubscribe(io.reactivex.Observer)} + * instead of the standard {@code subscribe()} method. + * + *
Example All pre-implemented final methods are thread-safe.
+ *
+ * Like all other consumers, {@code DisposableCompletableObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onError(Throwable)} and
+ * {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ *
+ * Example All pre-implemented final methods are thread-safe.
+ *
+ * Note that {@link #onSuccess(Object)}, {@link #onError(Throwable)} and {@link #onComplete()} are
+ * exclusive to each other, unlike a regular {@link io.reactivex.Observer Observer}, and
+ * {@code onComplete()} is never called after an {@code onSuccess()}.
+ *
+ * Like all other consumers, {@code DisposableMaybeObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onSuccess(Object)}, {@link #onError(Throwable)} and
+ * {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ *
+ * Example All pre-implemented final methods are thread-safe.
+ *
+ * Use the protected {@link #dispose()} to dispose the sequence from within an
+ * {@code onNext} implementation.
+ *
+ * Like all other consumers, {@code DefaultObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ * If for some reason this can't be avoided, use {@link io.reactivex.Observable#safeSubscribe(io.reactivex.Observer)}
+ * instead of the standard {@code subscribe()} method.
+ *
+ * Example All pre-implemented final methods are thread-safe.
+ *
+ * Like all other consumers, {@code DisposableSingleObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onSuccess(Object)} and {@link #onError(Throwable)}
+ * are not allowed to throw any unchecked exceptions.
+ *
+ * Example All pre-implemented final methods are thread-safe.
+ *
+ * Override the protected {@link #onStart()} to perform initialization when this
+ * {@code ResourceCompletableObserver} is subscribed to a source.
+ *
+ * Use the protected {@link #dispose()} to dispose the sequence externally and release
+ * all resources.
+ *
+ * To release the associated resources, one has to call {@link #dispose()}
+ * in {@code onError()} and {@code onComplete()} explicitly.
+ *
+ * Use {@link #add(Disposable)} to associate resources (as {@link io.reactivex.disposables.Disposable Disposable}s)
+ * with this {@code ResourceCompletableObserver} that will be cleaned up when {@link #dispose()} is called.
+ * Removing previously associated resources is not possible but one can create a
+ * {@link io.reactivex.disposables.CompositeDisposable CompositeDisposable}, associate it with this
+ * {@code ResourceCompletableObserver} and then add/remove resources to/from the {@code CompositeDisposable}
+ * freely.
+ *
+ * Like all other consumers, {@code ResourceCompletableObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ *
+ * Example All pre-implemented final methods are thread-safe.
*
+ * Note that {@link #onSuccess(Object)}, {@link #onError(Throwable)} and {@link #onComplete()} are
+ * exclusive to each other, unlike a regular {@link io.reactivex.Observer Observer}, and
+ * {@code onComplete()} is never called after an {@code onSuccess()}.
+ *
+ * Override the protected {@link #onStart()} to perform initialization when this
+ * {@code ResourceMaybeObserver} is subscribed to a source.
+ *
+ * Use the protected {@link #dispose()} to dispose the sequence externally and release
+ * all resources.
+ *
+ * To release the associated resources, one has to call {@link #dispose()}
+ * in {@code onSuccess()}, {@code onError()} and {@code onComplete()} explicitly.
+ *
+ * Use {@link #add(Disposable)} to associate resources (as {@link io.reactivex.disposables.Disposable Disposable}s)
+ * with this {@code ResourceMaybeObserver} that will be cleaned up when {@link #dispose()} is called.
+ * Removing previously associated resources is not possible but one can create a
+ * {@link io.reactivex.disposables.CompositeDisposable CompositeDisposable}, associate it with this
+ * {@code ResourceMaybeObserver} and then add/remove resources to/from the {@code CompositeDisposable}
+ * freely.
+ *
+ * Like all other consumers, {@code ResourceMaybeObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onSuccess(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ *
+ * Example All pre-implemented final methods are thread-safe.
*
+ * To release the associated resources, one has to call {@link #dispose()}
+ * in {@code onError()} and {@code onComplete()} explicitly.
+ *
+ * Use {@link #add(Disposable)} to associate resources (as {@link io.reactivex.disposables.Disposable Disposable}s)
+ * with this {@code ResourceObserver} that will be cleaned up when {@link #dispose()} is called.
+ * Removing previously associated resources is not possible but one can create a
+ * {@link io.reactivex.disposables.CompositeDisposable CompositeDisposable}, associate it with this
+ * {@code ResourceObserver} and then add/remove resources to/from the {@code CompositeDisposable}
+ * freely.
+ *
+ * Use the {@link #dispose()} to dispose the sequence from within an
+ * {@code onNext} implementation.
+ *
+ * Like all other consumers, {@code ResourceObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ * If for some reason this can't be avoided, use {@link io.reactivex.Observable#safeSubscribe(io.reactivex.Observer)}
+ * instead of the standard {@code subscribe()} method.
+ *
+ * Example All pre-implemented final methods are thread-safe.
*
+ * Override the protected {@link #onStart()} to perform initialization when this
+ * {@code ResourceSingleObserver} is subscribed to a source.
+ *
+ * Use the protected {@link #dispose()} to dispose the sequence externally and release
+ * all resources.
+ *
+ * To release the associated resources, one has to call {@link #dispose()}
+ * in {@code onSuccess()} and {@code onError()} explicitly.
+ *
+ * Use {@link #add(Disposable)} to associate resources (as {@link io.reactivex.disposables.Disposable Disposable}s)
+ * with this {@code ResourceSingleObserver} that will be cleaned up when {@link #dispose()} is called.
+ * Removing previously associated resources is not possible but one can create a
+ * {@link io.reactivex.disposables.CompositeDisposable CompositeDisposable}, associate it with this
+ * {@code ResourceSingleObserver} and then add/remove resources to/from the {@code CompositeDisposable}
+ * freely.
+ *
+ * Like all other consumers, {@code ResourceSingleObserver} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Disposable already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onSuccess(Object)} and {@link #onError(Throwable)}
+ * are not allowed to throw any unchecked exceptions.
+ *
+ * Example Note that onSubscribe is not serialized in respect of the other methods so
- * make sure the Subscription is set before any of the other methods are called.
+ * Note that {@link #onSubscribe(Disposable)} is not serialized in respect of the other methods so
+ * make sure the {@code onSubscribe()} is called with a non-null {@code Disposable}
+ * before any of the other methods are called.
*
- * The implementation assumes that the actual Subscriber's methods don't throw.
+ * The implementation assumes that the actual Observer's methods don't throw.
*
* @param All pre-implemented final methods are thread-safe.
+ *
+ * The default {@link #onStart()} requests Long.MAX_VALUE by default. Override
+ * the method to request a custom positive amount.
+ *
+ * Note that calling {@link #request(long)} from {@link #onStart()} may trigger
+ * an immediate, asynchronous emission of data to {@link #onNext(Object)}. Make sure
+ * all initialization happens before the call to {@code request()} in {@code onStart()}.
+ * Calling {@link #request(long)} inside {@link #onNext(Object)} can happen at any time
+ * because by design, {@code onNext} calls from upstream are non-reentrant and non-overlapping.
+ *
+ * Use the protected {@link #cancel()} to cancel the sequence from within an
+ * {@code onNext} implementation.
+ *
+ * Like all other consumers, {@code DefaultSubscriber} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Subscription already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ * If for some reason this can't be avoided, use {@link io.reactivex.Flowable#safeSubscribe(org.reactivestreams.Subscriber)}
+ * instead of the standard {@code subscribe()} method.
* @param Example All pre-implemented final methods are thread-safe.
+ *
+ * The default {@link #onStart()} requests Long.MAX_VALUE by default. Override
+ * the method to request a custom positive amount. Use the protected {@link #request(long)}
+ * to request more items and {@link #cancel()} to cancel the sequence from within an
+ * {@code onNext} implementation.
+ *
+ * Note that calling {@link #request(long)} from {@link #onStart()} may trigger
+ * an immediate, asynchronous emission of data to {@link #onNext(Object)}. Make sure
+ * all initialization happens before the call to {@code request()} in {@code onStart()}.
+ * Calling {@link #request(long)} inside {@link #onNext(Object)} can happen at any time
+ * because by design, {@code onNext} calls from upstream are non-reentrant and non-overlapping.
+ *
+ * Like all other consumers, {@code DefaultSubscriber} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Subscription already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ * If for some reason this can't be avoided, use {@link io.reactivex.Flowable#safeSubscribe(org.reactivestreams.Subscriber)}
+ * instead of the standard {@code subscribe()} method.
+ *
+ * Example This implementation let's you chose if the AsyncObserver manages resources or not,
- * thus saving memory on cases where there is no need for that.
+ * An abstract Subscriber that allows asynchronous cancellation of its
+ * subscription and associated resources.
*
* All pre-implemented final methods are thread-safe.
*
+ * To release the associated resources, one has to call {@link #dispose()}
+ * in {@code onError()} and {@code onComplete()} explicitly.
+ *
+ * Use {@link #add(Disposable)} to associate resources (as {@link io.reactivex.disposables.Disposable Disposable}s)
+ * with this {@code ResourceSubscriber} that will be cleaned up when {@link #dispose()} is called.
+ * Removing previously associated resources is not possible but one can create a
+ * {@link io.reactivex.disposables.CompositeDisposable CompositeDisposable}, associate it with this
+ * {@code ResourceSubscriber} and then add/remove resources to/from the {@code CompositeDisposable}
+ * freely.
+ *
+ * The default {@link #onStart()} requests Long.MAX_VALUE by default. Override
+ * the method to request a custom positive amount. Use the protected {@link #request(long)}
+ * to request more items and {@link #dispose()} to cancel the sequence from within an
+ * {@code onNext} implementation.
+ *
+ * Note that calling {@link #request(long)} from {@link #onStart()} may trigger
+ * an immediate, asynchronous emission of data to {@link #onNext(Object)}. Make sure
+ * all initialization happens before the call to {@code request()} in {@code onStart()}.
+ * Calling {@link #request(long)} inside {@link #onNext(Object)} can happen at any time
+ * because by design, {@code onNext} calls from upstream are non-reentrant and non-overlapping.
+ *
+ * Like all other consumers, {@code ResourceSubscriber} can be subscribed only once.
+ * Any subsequent attempt to subscribe it to a new source will yield an
+ * {@link IllegalStateException} with message {@code "Subscription already set!"}.
+ *
+ * Implementation of {@link #onStart()}, {@link #onNext(Object)}, {@link #onError(Throwable)}
+ * and {@link #onComplete()} are not allowed to throw any unchecked exceptions.
+ * If for some reason this can't be avoided, use {@link io.reactivex.Flowable#safeSubscribe(org.reactivestreams.Subscriber)}
+ * instead of the standard {@code subscribe()} method.
+ *
+ * Example Note that onSubscribe is not serialized in respect of the other methods so
- * make sure the Subscription is set before any of the other methods are called.
+ * Note that {@link #onSubscribe(Subscription)} is not serialized in respect of the other methods so
+ * make sure the {@code onSubscribe} is called with a non-null {@code Subscription}
+ * before any of the other methods are called.
*
* The implementation assumes that the actual Subscriber's methods don't throw.
*
+ *
* @param
+ * Disposable d =
+ * Observable.range(1, 5)
+ * .subscribeWith(new DefaultObserver<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * cancel();
+ * }
+ * System.out.println(t);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
*/
public abstract class DisposableCompletableObserver implements CompletableObserver, Disposable {
final AtomicReference
+ * Disposable d =
+ * Completable.complete().delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new DisposableMaybeObserver<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
+ *
* @param
+ * Disposable d =
+ * Maybe.just(1).delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new DisposableMaybeObserver<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * }
+ * @Override public void onSuccess(Integer t) {
+ * System.out.println(t);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Observable.range(1, 5)
+ * .subscribeWith(new DisposableObserver<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * dispose();
+ * }
+ * System.out.println(t);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Single.just(1).delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new DisposableSingleObserver<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * }
+ * @Override public void onSuccess(Integer t) {
+ * System.out.println(t);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
*/
public abstract class ResourceCompletableObserver implements CompletableObserver, Disposable {
/** The active subscription. */
diff --git a/src/main/java/io/reactivex/observers/ResourceMaybeObserver.java b/src/main/java/io/reactivex/observers/ResourceMaybeObserver.java
index c116ab1e57..9cb97a689a 100644
--- a/src/main/java/io/reactivex/observers/ResourceMaybeObserver.java
+++ b/src/main/java/io/reactivex/observers/ResourceMaybeObserver.java
@@ -26,6 +26,59 @@
*
*
+ * Disposable d =
+ * Completable.complete().delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new ResourceCompletableObserver() {
+ * @Override public void onStart() {
+ * add(Schedulers.single()
+ * .scheduleDirect(() -> System.out.println("Time!"),
+ * 2, TimeUnit.SECONDS));
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * dispose();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * dispose();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Maybe.just(1).delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new ResourceMaybeObserver<Integer>() {
+ * @Override public void onStart() {
+ * add(Schedulers.single()
+ * .scheduleDirect(() -> System.out.println("Time!"),
+ * 2, TimeUnit.SECONDS));
+ * }
+ * @Override public void onSuccess(Integer t) {
+ * System.out.println(t);
+ * dispose();
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * dispose();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * dispose();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Observable.range(1, 5)
+ * .subscribeWith(new ResourceObserver<Integer>() {
+ * @Override public void onStart() {
+ * add(Schedulers.single()
+ * .scheduleDirect(() -> System.out.println("Time!"),
+ * 2, TimeUnit.SECONDS));
+ * request(1);
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * dispose();
+ * }
+ * System.out.println(t);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * dispose();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * dispose();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Single.just(1).delay(1, TimeUnit.SECONDS)
+ * .subscribeWith(new ResourceSingleObserver<Integer>() {
+ * @Override public void onStart() {
+ * add(Schedulers.single()
+ * .scheduleDirect(() -> System.out.println("Time!"),
+ * 2, TimeUnit.SECONDS));
+ * }
+ * @Override public void onSuccess(Integer t) {
+ * System.out.println(t);
+ * dispose();
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * dispose();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
*/
public abstract class DefaultSubscriber
+ * Disposable d =
+ * Flowable.range(1, 5)
+ * .subscribeWith(new DefaultSubscriber<Integer>() {
+ * @Override public void onStart() {
+ * System.out.println("Start!");
+ * request(1);
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * cancel();
+ * }
+ * System.out.println(t);
+ * request(1);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
* @param
+ * Disposable d =
+ * Flowable.range(1, 5)
+ * .subscribeWith(new DisposableSubscriber<Integer>() {
+ * @Override public void onStart() {
+ * request(1);
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * cancel();
+ * }
+ * System.out.println(t);
+ * request(1);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *
+ *
* @param
+ * Disposable d =
+ * Flowable.range(1, 5)
+ * .subscribeWith(new ResourceSubscriber<Integer>() {
+ * @Override public void onStart() {
+ * add(Schedulers.single()
+ * .scheduleDirect(() -> System.out.println("Time!"),
+ * 2, TimeUnit.SECONDS));
+ * request(1);
+ * }
+ * @Override public void onNext(Integer t) {
+ * if (t == 3) {
+ * dispose();
+ * }
+ * System.out.println(t);
+ * request(1);
+ * }
+ * @Override public void onError(Throwable t) {
+ * t.printStackTrace();
+ * dispose();
+ * }
+ * @Override public void onComplete() {
+ * System.out.println("Done!");
+ * dispose();
+ * }
+ * });
+ * // ...
+ * d.dispose();
+ *