Briefly:
Several main needs
- Create an Observable directly
- Combining multiple observables
- Perform transform operation (transform operation) on the data transmitted by Observable
- Take a specific value from the data transmitted by Observable (filtering operation)
- Forward partial value of Observable (conditional / Boolean / filter operation)
- Evaluate the data sequence emitted by Observable (arithmetic / aggregate operation)
Various ways to create Observable
- create(): create an Observable from scratch using a function
- defer(): create an Observable only when the subscriber subscribes; create a new Observable for each subscription
- empty(): create an Observable that does nothing to directly notify the completion
- never(): create an Observable without launching any data
- error(): - create an Observable that does nothing to directly notify the error
- just(): converts one or more objects to an Observable that emits this or these objects
- from(): convert an Iterable, a Future, or an array to an Observable
- repeat(): creates an Observable that repeatedly emits the specified data or data sequence
- repeatWhen(): creates an Observable that repeatedly emits the specified data or data sequence, which depends on the data emitted by another Observable
- repeatUntil(): judge whether to continue the subscription according to the condition (function Boolean supplier)
- range(): creates an Observable that emits a sequence of integers in a specified range
- interval(): creates an Observable that emits an integer sequence at a given time interval
- timer(): - creates an Observable that emits a single data after a given delay
1. Create
Use the Create operator to Create an Observable from the beginning, and pass a function that accepts the observer as a parameter to the operator. Write this function to call the observer's onNext, onError and onCompleted methods. When a subscription occurs, the observer's onSubscribe method will be called automatically.
Subscribe to the Observable and Observer through the subscribe method. The subscribe method can receive an Observer object with a complete notification parameter, or a consumer or Action object with partial notification parameters.
Instance code:
// Create observable Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() { public void subscribe(ObservableEmitter<String> emitter) throws Exception { emitter.onNext("Hello"); emitter.onNext("World"); emitter.onComplete(); } }); // Create observer to accept all notifications Observer<String> observer = new Observer<String>() { public void onSubscribe(Disposable d) { System.out.println("--> onSubscribe"); } public void onNext(String t) { System.out.println("--> onNext = " + t); } public void onError(Throwable e) { System.out.println("--> onError"); } public void onComplete() { System.out.println("--> onComplete"); } }; // Create a consumer (observer) that accepts only onNext(item) notifications Consumer<String> nextConsumer = new Consumer<String>() { @Override public void accept(String t) throws Exception { System.out.println("--> accept nextConsumer: " + t); } }; // Create a consumer (observer) that accepts only onError(Throwable) notifications Consumer<Throwable> errorConsumer = new Consumer<Throwable>() { @Override public void accept(Throwable t) throws Exception { System.out.println("-- accept errorConsumer: " + t); } }; // Create an action (observer) that only accepts onComplete() notifications Action completedAction = new Action() { @Override public void run() throws Exception { System.out.println("--> run completedAction"); } }; // Create a consumer (observer) that only accepts onSubscribe notifications Consumer<Disposable> onSubscribeComsumer = new Consumer<Disposable>() { @Override public void accept(Disposable t) throws Exception { System.out.println("--> accept onSubscribeComsumer "); } }; // 1. subscribe(Observer) observable.subscribe(observer); System.out.println("---------------------------------------------"); // 2. subscribe(Consumer onNext) observable.subscribe(nextConsumer); System.out.println("---------------------------------------------"); // 3. subscribe(Consumer onNext, Consumer onError) observable.subscribe(nextConsumer, errorConsumer); System.out.println("---------------------------------------------"); // 4. subscribe(Consumer onNext, Consumer onError, Action onCompleted) observable.subscribe(nextConsumer, errorConsumer, completedAction); System.out.println("---------------------------------------------"); // 5. subscribe(Consumer onNext, Consumer onError, Action onCompleted, Consumer onSubscribe) observable.subscribe(nextConsumer, errorConsumer, completedAction, onSubscribeComsumer);
Output:
--> onSubscribe --> onNext = Hello --> onNext = World --> onComplete --------------------------------------------- --> accept nextConsumer: Hello --> accept nextConsumer: World --------------------------------------------- --> accept nextConsumer: Hello --> accept nextConsumer: World --------------------------------------------- --> accept nextConsumer: Hello --> accept nextConsumer: World --> run completedAction --------------------------------------------- --> accept onSubscribeComsumer --> accept nextConsumer: Hello --> accept nextConsumer: World --> run completedAction
Be careful: create Method is not executed on any specific scheduler by default.
onSubscribe(Disposable): Received when a subscription occurs.
onNext(item): Data reception is transmitted to the observed.
onError(Throwable): Launched by the observed Error Time to receive.
onComplete(): Received when the observed completes data transmission.
Javadoc: create(OnSubscribe) Javadoc: subscribe()
Javadoc: subscribe(observer)
Javadoc: subscribe(onNext)
Javadoc: subscribe(onNext, onError)
Javadoc: subscribe(onNext, onError, onComplete)
Javadoc: subscribe(onNext, onError, onComplete, onSubscribe)
2. Defer
The Observable is not created until there is an observer subscription, and a new Observable is created for each observer
The Defer operator waits until an observer subscribes to it, and then it uses the Observable factory method to generate an Observable. It does this for each observer, so even though each subscriber thinks they are subscribed to the same Observable, in fact, each subscriber gets its own separate data sequence.
Instance code:
// Create an Observable of type Defer Observable<Integer> deferObservable = Observable.defer(new Callable<ObservableSource<? extends Integer>>() { public ObservableSource<? extends Integer> call() throws Exception { // Create the Observable returned by each observer subscription Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() { public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { emitter.onNext(1); emitter.onNext(2); emitter.onNext(3); emitter.onNext(4); emitter.onNext(5); emitter.onComplete(); } }); return observable; } }); // Create the first observer and subscribe to defer Observable deferObservable.subscribe(new Consumer<Integer>() { public void accept(Integer t) throws Exception { System.out.println("No.1 --> accept = " + t); } }); // Create a second observer and subscribe to defer Observable deferObservable.subscribe(new Consumer<Integer>() { public void accept(Integer t) throws Exception { System.out.println("No.2 --> accept = " + t); } }); // Create a third observer and subscribe to defer Observable deferObservable.subscribe(new Consumer<Integer>() { public void accept(Integer t) throws Exception { System.out.println("No.3 --> accept = " + t); } });
Output:
No.1 --> accept = 1 No.1 --> accept = 2 No.1 --> accept = 3 No.1 --> accept = 4 No.1 --> accept = 5 No.2 --> accept = 1 No.2 --> accept = 2 No.2 --> accept = 3 No.2 --> accept = 4 No.2 --> accept = 5 No.3 --> accept = 1 No.3 --> accept = 2 No.3 --> accept = 3 No.3 --> accept = 4 No.3 --> accept = 5
Note: the defer method is not executed on any specific scheduler by default.
Javadoc: defer(Func0)
3. Empty/Never/Error
Empty: create an Observable that does not emit any data but terminates normally Never: create an Observable that does not transmit data or terminate Error: create an Observable that does not emit data and terminates with an error
The Observable behavior generated by these three operators is very special and limited, and is mostly used in some special scenarios (some operation state exceptions return an error, empty, never Observable). It is very useful when testing, sometimes it is also used to combine other Observables, or as parameters of other operators that need Observable.
Instance code:
System.out.println("--> 1 -----------------------------------"); // 1. Create an Observable that does not transmit any data but terminates normally Observable.empty() .subscribe(new Observer<Object>() { @Override public void onSubscribe(Disposable d) { System.out.println("onSubscribe"); } @Override public void onNext(Object t) { System.out.println("onNext: " + t); } @Override public void onError(Throwable e) { System.out.println("onError: " + e); } @Override public void onComplete() { System.out.println("onComplete"); } }); System.out.println("--> 2 -----------------------------------"); // 2. Create an Observable that does not output data and will not terminate Observable.never() .subscribe(new Observer<Object>() { @Override public void onSubscribe(Disposable d) { System.out.println("onSubscribe"); } @Override public void onNext(Object t) { System.out.println("onNext: " + t); } @Override public void onError(Throwable e) { System.out.println("onError: " + e); } @Override public void onComplete() { System.out.println("onComplete"); } }); System.out.println("--> 3 -----------------------------------"); // 3. Create an Observable that does not transmit data and terminates with an error Observable.error(new NullPointerException("error test")) .subscribe(new Observer<Object>() { @Override public void onSubscribe(Disposable d) { System.out.println("onSubscribe"); } @Override public void onNext(Object t) { System.out.println("onNext: " + t); } @Override public void onError(Throwable e) { System.out.println("onError: " + e); } @Override public void onComplete() { System.out.println("onComplete"); } });
Output:
--> 1 ----------------------------------- onSubscribe onComplete --> 2 ----------------------------------- onSubscribe --> 3 ----------------------------------- onSubscribe onError: java.lang.NullPointerException: error test
Be careful:
- RxJava implements these operators as empty, never, and error.
- The error operator requires a Throwable parameter, which will terminate your Observable.
- These operators are not executed on any specific Scheduler by default, but an optional parameter for empty and error is Scheduler. If you pass the Scheduler parameter, they will send notifications on this Scheduler
Javadoc: empty()
Javadoc: never()
Javadoc: error(java.lang.Throwable)
4. Just
Creates an Observable that emits the specified value.
Just converts a single data into an Observable that transmits that data. It is similar to From, but From will take out the data of array or Iterable and launch them one by one, while just will simply launch as is, treating array or Iterable as a single data.
Note: if you pass null to Just, it will return an Observable that emits a null value. Don't mistake it for returning an Empty Observable. If you need an Empty Observable, you should use the Empty operator.
Instance code:
// Single object send Observable.just(1) .subscribe(new Consumer<Integer>() { public void accept(Integer t) throws Exception { System.out.println("--> singe accept: " + t); } }); System.out.println("---------------------------------"); // Multiple objects are sent, and the internal implementation is from (accepts one to nine parameters, and returns an observable that transmits these data in the order of parameter list) Observable.just(1, 2, 3, 4, 5) .subscribe(new Consumer<Integer>() { public void accept(Integer t) throws Exception { System.out.println("--> mutil accept: " + t); } });
Output:
--> singe accept: 1 --------------------------------- --> mutil accept: 1 --> mutil accept: 2 --> mutil accept: 3 --> mutil accept: 4 --> mutil accept: 5
Javadoc: just(item ...)
5. From
Convert other kinds of objects and data types to Observable, transmit data from corresponding data source data types. In RxJava, the from operator can convert Future, Iterable and array. For Iterable and array, the resulting Observable will emit every item of data of Iterable or array.
Instance code:
// Initialization data Integer[] array = { 1, 2, 3, 4, 5, 6 }; List<String> iterable = new ArrayList<String>(); iterable.add("A"); iterable.add("B"); iterable.add("C"); iterable.add("D"); iterable.add("E"); // 1. fromArray Observable.fromArray(array).subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept(1):fromArray: " + t); } }); System.out.println("---------------------------------------"); // 2. fromIterable Observable.fromIterable(iterable) .subscribe(new Consumer<String>() { @Override public void accept(String t) throws Exception { System.out.println("--> accept(2) fromIterable: " + t); } }); System.out.println("---------------------------------------"); // 3. fromCallable Observable.fromCallable(new Callable<Integer>() { @Override public Integer call() throws Exception { return 1; } }).subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept(3): fromCallable: " + t); } }); System.out.println("---------------------------------------"); // 4. fromFuture Observable.fromFuture(new Future<String>() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public String get() throws InterruptedException, ExecutionException { System.out.println("--> fromFutrue: get()"); return "hello"; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return false; } @Override public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return null; } }).subscribe(new Consumer<String>() { @Override public void accept(String t) throws Exception { System.out.println("--> accept(4): fromFuture: " + t); } });
Output:
--> accept(1):fromArray: 1 --> accept(1):fromArray: 2 --> accept(1):fromArray: 3 --> accept(1):fromArray: 4 --> accept(1):fromArray: 5 --> accept(1):fromArray: 6 --------------------------------------- --> accept(2) fromIterable: A --> accept(2) fromIterable: B --> accept(2) fromIterable: C --> accept(2) fromIterable: D --> accept(2) fromIterable: E --------------------------------------- --> accept(3): fromCallable: 1 --------------------------------------- --> fromFutrue: get() --> accept(4): fromFuture: hello
Be careful: from By default, it does not execute on any specific scheduler. But you can Scheduler Passed as an optional second parameter to Observable,It will manage this on that scheduler Future.
Javadoc: from(array)
Javadoc: from(Iterable)
Javadoc: from(Callable)
Javadoc: from(Future)
Javadoc: from(Future,Scheduler)
Javadoc: from(Future,timeout,timeUnit)
6. Repeat
Create an Observable that transmits specific data multiple times. Instead of creating an Observable, it repeatedly transmits the original Observable data sequence. This sequence is either infinite or specifies the number of repetitions through repeat(n).
Instance code:
// 1. repeat(): repeatedly transmit the original Observable data sequence Observable.range(1, 5) .repeat() .subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept(1): " + t); } }); System.out.println("----------------------------------------"); // 2. repeat(n): repeat 5 times Observable.range(1, 2) .repeat(3) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept(2): " + t); } });
Output:
--> accept(1): 1 --> accept(1): 2 --> accept(1): 3 --> accept(1): 4 --> accept(1): 5 --> accept(1): 1 --> accept(1): 2 --> accept(1): 3 --> accept(1): 4 --> accept(1): 5 --> accept(1): 1 --> accept(1): 2 --> accept(1): 3 --> accept(1): 4 --> accept(1): 5 ...... ---------------------------------------- --> accept(2): 1 --> accept(2): 2 --> accept(2): 1 --> accept(2): 2 --> accept(2): 1 --> accept(2): 2
Note: the repeat operator is executed on the trackoline Scheduler by default. There is a variation to specifying a Scheduler with optional parameters.
Javadoc: repeat()
Javadoc: repeat(long)
Javadoc: repeat(Scheduler)
Javadoc: repeat(long,Scheduler)
7. RepeatWhen
repeatWhen operator is not used to cache and replay the original Observable data sequence. After receiving the termination notice of the original Observable, it will conditionally decide whether to subscribe to the original Observable again.
The termination notification (completion or error) of the original Observable is passed as a void data to a notification processor, which decides whether to re subscribe and launch the original Observable. This notification processor is like an Observable operator. It accepts an Observable that sends a void notification as input, and returns an Observable that sends void data (that is, re subscribes to and transmits the original Observable) or directly terminates (that is, terminates the transmitted data with repeatWhen).
Instance code:
// repeatWhen(Func1()): after receiving the termination notice, decide whether to re subscribe to the original Observable in the function // It should be noted that the objectObservable processing of repeatWhen (you can also customize the Observable return separately). Here, we use flatmap for processing, // Let it delay the issue of onNext. Here, any data sent by onNext is not important. It is only used to process the notification of re subscription. If the issue is onComplete/onError, the re subscription will not be triggered Observable.range(1, 2) .doOnComplete(new Action() { @Override public void run() throws Exception { System.out.println("-----------> Complete a subscription"); } }).repeatWhen(new Function<Observable<Object>, ObservableSource<?>>() { private int n = 0; @Override public ObservableSource<?> apply(Observable<Object> t) throws Exception { // Receive the termination notice of the original Observable and decide whether to subscribe again System.out.println("--> apply repeat "); return t.flatMap(new Function<Object, ObservableSource<?>>() { @Override public ObservableSource<?> apply(Object t) throws Exception { if(n < 3) { // Re subscribe 3 times n ++; return Observable.just(0); } else { return Observable.empty(); } } }); // return Observable.timer(1, TimeUnit.SECONDS); / / re subscribe after one second // return Observable.interval(1, TimeUnit.SECONDS); / / re subscribe every second } }).subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept: " + t); } });
Output:
--> apply repeat --> accept: 1 --> accept: 2 ----------->Complete a subscription --> accept: 1 --> accept: 2 ----------->Complete a subscription --> accept: 1 --> accept: 2 ----------->Complete a subscription --> accept: 1 --> accept: 2 ----------->Complete a subscription
Note: the repeatWhen operator is executed on the trackoline scheduler by default.
Javadoc: repeatWhen(Func1)
8. RepeatUntil
Judge whether to continue subscription according to the condition (function Boolean supplier): false: continue subscription; true: cancel subscription
Instance code:
// repeatUntil determines whether to continue the subscription according to the condition (Boolean supplier) Observable.range(1, 2) .doOnComplete(new Action() { @Override public void run() throws Exception { System.out.println("-----------> Complete a subscription"); } }).repeatUntil(new BooleanSupplier() { private int n = 0; @Override public boolean getAsBoolean() throws Exception { System.out.println("getAsBoolean = " + (n < 3? false:true) ); // Termination required or not if (n < 3) { n++; return false; // Continue to unsubscribe } return true; // Terminate re subscription } }).subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("--> accept: " + t); } });
Output:
--> accept: 1 --> accept: 2 -----------> Complete a subscription getAsBoolean = false --> accept: 1 --> accept: 2 -----------> Complete a subscription getAsBoolean = false --> accept: 1 --> accept: 2 -----------> Complete a subscription getAsBoolean = false --> accept: 1 --> accept: 2 -----------> Complete a subscription getAsBoolean = true
Javadoc: repeatWhen(Func1)
9. Range
Creates an Observable that emits a specific sequence of integers.
The Range operator emits an ordered sequence of integers within a Range, and you can specify the start and length of the Range.
RxJava implements this operator as a range function, which takes two parameters, one is the starting value of the range and the other is the number of data in the range. If you set the second parameter to 0, it will cause Observable not to emit any data (if it is set to a negative number, it will throw an exception).
Instance code:
// 1. range(n,m) transmits m Integer Sequences starting from n, sequence interval [n, N + M-1] Observable.range(0, 5) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer t) throws Exception { System.out.println("-- accept(range): " + t); } }); System.out.println("------------------------------"); // 2. rangeLong(n,m) emits m long integer sequences starting from n, sequence interval [n, N + M-1] Observable.rangeLong(1, 5) .subscribe(new Consumer<Long>() { @Override public void accept(Long t) throws Exception { System.out.println("-- accept(rangeLong): " + t); } });
Output:
-- accept(range): 0 -- accept(range): 1 -- accept(range): 2 -- accept(range): 3 -- accept(range): 4 ------------------------------ -- accept(rangeLong): 1 -- accept(rangeLong): 2 -- accept(rangeLong): 3 -- accept(rangeLong): 4 -- accept(rangeLong): 5
Javadoc: range(int start,int count)
Javadoc: rangeLong(long start, long count)
10. interval
Create an Observable that emits an integer sequence at a fixed time interval, which emits an infinite increasing integer sequence at a fixed time interval.
RxJava implements this operator as an interval method. It takes a parameter that represents the time interval and a parameter that represents the time unit.
Instance code:
// [1] interval(long period, TimeUnit unit) // Every interval period time unit, transmit an integer sequence Observable.interval(1, TimeUnit.SECONDS) .subscribe(new Consumer<Long>() { public void accept(Long l) throws Exception { System.out.println("--> accept(1): " + l); } }); System.out.println("------------------------------------"); // [2] interval(long initialDelay, long period, TimeUnit unit) // Emit an integer sequence every period unit of time after the initial delay second Observable.interval(0, 1, TimeUnit.SECONDS) .subscribe(new Consumer<Long>() { public void accept(Long t) throws Exception { System.out.println("--> accept(2): " + t); } }); System.out.println("------------------------------------"); // [3] intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit) // After delaying initialDelay seconds, start from the start of the starting data, and send a number sequence every period seconds, with a total of count data sent Observable.intervalRange(1, 5, 3, 2, TimeUnit.SECONDS) .subscribe(new Consumer<Long>() { public void accept(Long t) throws Exception { System.out.println("--> accept(3): " + t); } });
Be careful: interval By default computation Executed on the scheduler with a variation that can be specified with optional parameters Scheduler.
Javadoc: interval(long period, TimeUnit unit)
Javadoc: interval(long period, TimeUnit unit, Scheduler scheduler)
Javadoc: interval(long initialDelay, long period, TimeUnit unit)
Javadoc: interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler)
Javadoc: intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit)
Javadoc: intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit, Scheduler scheduler)
Output:
--> accept(1): 0 --> accept(1): 1 --> accept(1): 2 --> accept(1): 3 --> accept(1): 4 --> accept(1): 5 ... ------------------------------------ --> accept(2): 0 --> accept(2): 1 --> accept(2): 2 --> accept(2): 3 --> accept(2): 4 --> accept(2): 5 ... ------------------------------------ --> accept(3): 1 --> accept(3): 2 --> accept(3): 3 --> accept(3): 4 --> accept(3): 5
11. Timer
Emit a special value of Observable after creating a given delay.
RxJava implements this operator as a timer function. Timer returns an Observable, which transmits a simple number 0 after a given delay
Instance code:
// timer(long delay, TimeUnit unit, Scheduler scheduler) // The number 0 is sent after the timing delay time unit, and the optional parameter Schedule scheduler is specified as Trampoline (the current thread is queued for execution) Observable.timer(5, TimeUnit.SECONDS, Schedulers.trampoline()) .subscribe(new Consumer<Long>() { @Override public void accept(Long t) throws Exception { System.out.println("--> accept: " + t); } });
Output:
--> accept: 0
Note: the timer operator is executed on the calculation Scheduler by default. There is a variation to specifying a Scheduler with optional parameters.
Javadoc: timer(long delay, TimeUnit unit)
Javadoc: timer(long delay, TimeUnit unit, Scheduler scheduler)
Summary
According to the actual situation, different kinds of observables are created in different ways, which is very useful in development. It can reduce a lot of repetitive, complex and redundant operations, and can quickly create an Observable that meets the requirements, which improves the efficiency of development to a certain extent.
Tip: Rxjava2 version used above: 2.2.12
Rx introduction and explanation and complete catalog reference: Rxjava2 introduction and detailed examples
Instance code: