What is RxJava?According to RxJava's description on GitHub:
RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java
It roughly means:
RxJava - A java library that runs on a JVM and implements asynchronous operations based on observer mode.
The role of RxJava:
It is the use of asynchronous RxJava that makes "code with complex logic" extremely readable.
Role of RxAndorid:
RxAndorid works with RxJava in Android; RxAndorid encapsulates Android Schedulers.mainThread(), which makes it easy for Android developers to perform page updates from the task post Andorid main thread.
Usage
1,Observable
- Observable: Observed
- Observer: Observer, which receives data sent by Observable
a. Rxjava implements thread switching:
// Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { //1.'Asynchronous Thread'performs time-consuming operations //2. Call onNext after execution to trigger callback and notify observer e.onNext("1"); e.onComplete(); } }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onSubscribe(Disposable d) { // The moment the subscription thread subscribes, it executes in the subscription thread } @Override public void onNext(String value) { // Method of Main Thread execution } @Override public void onError(Throwable e) { // Method of Main Thread execution } @Override public void onComplete() { // Method of Main Thread execution } });
b, Rxjava use operators
Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { // IO Threads // Request network data e.onNext("123456"); } }).map(new Function<String, Integer>() { @Override public Integer apply(String s) { // IO Threads // Network Data Parsing (Data Conversion) // // throw new RequestFailException("Failed to get network request"); return 123; } }).doOnNext(new Consumer<Integer>() { //Save logon results UserInfo @Override public void accept(@NonNull Integer bean) throws Exception { // IO Threads // Save network data } }).subscribeOn(Schedulers.io()) //Slave IO Thread .observeOn(AndroidSchedulers.mainThread()) //Main Thread .subscribe(new Consumer<Integer>() { @Override public void accept(@NonNull Integer bean) throws Exception { // Update UI } }, new Consumer<Throwable>() { @Override public void accept(@NonNull Throwable throwable) throws Exception { // Error Display Error Page } });
2,Flowable
Flowable s are generated in response to Backpressure s.
Flowable is an observer, used with Subscriber
// Flowable.create(new FlowableOnSubscribe<Integer>() { @Override public void subscribe(FlowableEmitter<Integer> emitter) throws Exception { //1.'Asynchronous Thread'performs time-consuming operations //2. Call onNext after execution to trigger callback and notify observer emitter.onNext(0); emitter.onComplete(); } // Throw MissingBackpressureException if consumer is not able to consume }, BackpressureStrategy.ERROR) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Integer>() { @Override public void onSubscribe(Subscription s) { // Executed at subscription time, occurring at Subscription Thread // This method is used to apply to producers for the number of events that can be consumed // This shows that consumers have the ability to consume Long.MAX_VALUE s.request(Long.MAX_VALUE); } @Override public void onNext(Integer integer) { // Method of Main Thread execution } @Override public void onError(Throwable t) { // Method of Main Thread execution } @Override public void onComplete() { // Method of Main Thread execution } });
a, Backpressure
Backpressure is a problem caused by a producer's production speed being faster than a consumer's ability to consume.
In RxJava, there is a situation where the observer sends messages so quickly that the observer cannot respond to them in time.
For example:
Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { // Producers in Asynchronous Threads have unlimited productivity while (true){ e.onNext(1); } } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { // Insufficient consumer spending in the Main Thread, resulting in an infinite accumulation of events and eventually OOM Thread.sleep(2000); System.out.println(integer); } });
Producers in asynchronous threads have unlimited productivity;
Insufficient consumer spending power in the main thread causes events to accumulate indefinitely, eventually resulting in OOM.
In the above phenomenon, there is a unique noun to describe it: Backpressure
b,Subscription.request(long n);
The Subscription.request(long n) method is used to apply to the producer for the number of events that can be consumed.
- When the request(long n) method is called, the producer sends a corresponding number of events for consumers to consume.
- If the call request is not shown, the consumption power is zero.
When invoked asynchronously, RxJava has a cache pool for caching data that consumers cannot handle temporarily cached. The default size of the cache pool is 128, which means only 128 events can be cached.
Whether the number passed in from request() is larger or smaller than 128, 128 events will be stored in the cache pool at first; of course, 128 events will not be stored if there are not so many events to send themselves.
- Under the BackpressureStrategy.ERROR policy, if the producer produces more than 128 events, the cache pool overflows, throwing the MissingBackpressureException exception.
- BackpressureStrategy.BUFFER policy: Replace the default 128 events cache pool in RxJava with a larger cache pool so that consumers can produce events through request() even if a large number is passed in.However, this method consumes more memory, unless we have a better understanding of the consumer's consumption capacity and can grasp the specific situation, OOM will not be generated.In short, BUFFER should be used with caution.
- BackpressureStrategy.DROP policy: discard when consumer cannot handle the event.Consumers pass in their demand n through request(), and producers pass n events to consumers for consumption.Everything else you can't spend is lost.
- BackpressureStrategy.LATEST Policy: LATEST and DROP functionality are basically the same.Consumers pass in their demand n through request(), and producers pass n events to consumers for consumption.Everything else you can't spend is lost.The only difference is that LATEST always enables consumers to receive the last event from the producer.
Source reading - a simple example (1)
Note: Source version currently in use rxjava:2.1.9
Start with this simple example that does not involve operator and thread switching:
//Create an observer Observer observer = new Observer<String>() { @Override public void onSubscribe(@NonNull Disposable d) { Log.d(TAG, "onSubscribe"); } @Override public void onNext(String o) { } @Override public void onError(@NonNull Throwable e) { Log.d(TAG, "onError data is :" + e.toString()); } @Override public void onComplete() { Log.d(TAG, "onComplete"); } }; //Create Observed Observable observable = Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { e.onNext("hello"); e.onNext("world"); e.onComplete(); } }); //Subscription observable.subscribe(observer);
a,ObservableOnSubscribe.java
First look at the ObservableOnSubscribe.java class
public interface ObservableOnSubscribe<T> { void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception; }
The code shows that ObservableOnSubscribe is a callback interface. The parameter in the callback method is ObservableEmitter. Look at the class ObservableEmitter below.
ObservableEmitter.java
ObservableEmitter literally means the observee transmitter, take a look at the source code:
public interface ObservableEmitter<T> extends Emitter<T> { void setDisposable(@Nullable Disposable d); void setCancellable(@Nullable Cancellable c); boolean isDisposed(); @NonNull ObservableEmitter<T> serialize(); @Experimental boolean tryOnError(@NonNull Throwable t); }
ObservableEmitter is an extension to Emitter that was introduced after RxJava 2.0.New capabilities are available, such as cancel in the middle. Let's look at Emitter source:
public interface Emitter<T> { void onNext(@NonNull T value); void onError(@NonNull Throwable error); void onComplete(); }
Emitter literally means a transmitter. The three methods here are familiar to everyone.It corresponds to the following code:
new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { e.onNext("hello"); e.onNext("world"); e.onComplete(); } }
With that callback in mind, let's move on to Observable.create (ObservableOnSubscribe<T> source).
b,Observable.create(ObservableOnSubscribe<T> source)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) { ObjectHelper.requireNonNull(source, "source is null"); return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source)); }
- RxJavaPlugins ignored first
- We see that the incoming ObservableOnSubscribe is used to create ObservableCreate, which is actually an implementation class of Observable
So the Observable.create (ObservableOnSubscribe<T> source) code is actually:
// ObservableCreate observableCreate = new ObservableCreate<T>(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { // Execution in IO Thread e.onNext("hello"); e.onNext("world"); e.onComplete(); } });
- Here we know that when the ObservableOnSubscribe.subscribe method is executed, the user sends data (to the observer) by calling the ObservableEmitter.onNext method
Next let's look at the ObservableCreate class
public final class ObservableCreate<T> extends Observable<T> { final ObservableOnSubscribe<T> source; public ObservableCreate(ObservableOnSubscribe<T> source) { this.source = source; } @Override protected void subscribeActual(Observer<? super T> observer) { CreateEmitter<T> parent = new CreateEmitter<T>(observer); observer.onSubscribe(parent); try { source.subscribe(parent); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); parent.onError(ex); } } // Omit some code... }
- The ObservableOnSubscribe.subscribe method is executed in the fourth line of the ObservableCreate.subscribeActual method, where the user sends data by calling the ObservableEmitter.onNext method;
- The second line of the subscribeActual method calls observer.onSubscribe(parent); the method.When a subscription occurs, the onSubscribe method of the observer is actively executed by the subscription thread;
- CreateEmitter is the encapsulation of Observer passed in by ObservableCreate.subscribeActual (Observer<? Super T> observer) method;
- The purpose of CreateEmitter is that when a task is cancelled, its encapsulated observer can no longer be called back; the onNext method of the observer is called by the CreateEmitter.onNext method;
Observable.create (ObservableOnSubscribe<T> source); method eventually returns an ObservableCreate object.
Look below at observable.subscribe(observer); method
c,observable.subscribe(observer);
- observable.subscribe(observer); that is, the moment the subscription occurs.
- Here observable.subscribe(observer); actually ObservableCreate.subscribe(observer);
View Observable's subscribe(observer) method below
Observable.subscribe(Observer observer)
public final void subscribe(Observer<? super T> observer) { ObjectHelper.requireNonNull(observer, "observer is null"); try { observer = RxJavaPlugins.onSubscribe(this, observer); ObjectHelper.requireNonNull(observer, "Plugin returned null Observer"); // Observable's subscribe method, which actually executes the subscribeActual method subscribeActual(observer); } catch (NullPointerException e) { // NOPMD throw e; } catch (Throwable e) { Exceptions.throwIfFatal(e); RxJavaPlugins.onError(e); // NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS"); npe.initCause(e); throw npe; } }
- When you call observable.subscribe(observer); when you call a method, you actually call the observable.subscribeActual(observer) method.
- observable is a reference to ObservableCreate, so the ObservableCreate.subscribeActual(observer) method is called here.
Let's go back to the subscribeActual method of ObservableCreate
ObservableCreate.java
public final class ObservableCreate<T> extends Observable<T> { final ObservableOnSubscribe<T> source; public ObservableCreate(ObservableOnSubscribe<T> source) { this.source = source; } // The subscribeActual method is called both observable.subscribe(observer) at the moment the subscription occurs; it is called @Override protected void subscribeActual(Observer<? super T> observer) { // If the midway task is cancelled, callbacks to methods onNext, onError, and so on in the observer can be terminated by CreateEmitter CreateEmitter<T> parent = new CreateEmitter<T>(observer); // Execute the observer's onSubscribe(Disposable d) method when a subscription occurs observer.onSubscribe(parent); try { source.subscribe(parent); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); parent.onError(ex); } } // Omit some code... }
- The subscribeActual method is called at the moment the subscription occurs; at observable.subscribe(observer); and
- observer.onSubscribe(parent); when a subscription occurs, the subscription thread calls back the observer's onSubscribe method
- In the subscribeActual method, the incoming Observer is wrapped as a CreateEmitter; if the task is cancelled in the middle, the callbacks to the methods onNext, onError, and so on, in the observer can be terminated by CreateEmitter;
The second line of code in subscribeActual, observer.onSubscribe(parent);
observer.onSubscribe(parent); when a subscription occurs, the observer's onSubscribe(Disposable d) method is executed, returning to the following code
// Create an observer Observer observer = new Observer<String>() { @Override public void onSubscribe(@NonNull Disposable d) { Log.d(TAG, "onSubscribe"); } // ...omit onNext, onError, onComplete };
- The parameter passed in here is new CreateEmitter <T> (observer), which implements the Disposable interface. If the task is cancelled, the onNext, onError, onComplete methods corresponding to the incoming observer observer will not be callback.
The fourth line of code in subscribeActual, source.subscribe(parent);
source.subscribe(parent); ObservableOnSubscribe.subscribe (new CreateEmitter<T> (observer));
The code eventually returns to ObservableOnSubscribe's subscribe:
new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { e.onNext("hello"); e.onNext("world"); e.onComplete(); } }
- In subscribe, the onNext, onComplete, onError methods of the CreateEmitter class are called to send data to the observer in CreateEmitter
At this point, the code tracking for this simple example of no operator or thread switching ends.
Source Reading - Thread Switching (2)
Note: Source version currently in use rxjava:2.1.9
Start with a simple example of this thread switch:
// Create an observer Observer observer = new Observer<String>() { @Override public void onSubscribe(@NonNull Disposable d) { // The moment the subscription thread subscribes, it executes in the subscription thread } @Override public void onNext(String o) { // Execute in Android main thread } @Override public void onError(@NonNull Throwable e) { // Execute in Android main thread } @Override public void onComplete() { // Execute in Android main thread } }; // Create Observed Observable observable = Observable.create(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { // Execution in IO Thread e.onNext("hello"); e.onNext("world"); e.onComplete(); } }); // Observed IO Threads observable = observable.subscribeOn(Schedulers.io()); // Observer Android Main Thread observable = observable.observeOn(AndroidSchedulers.mainThread()); // Subscribe observable.subscribe(observer);
First, let me summarize the entire code execution process for RxJava2:
a,Observable.create(ObservableOnSubscribe<T> source)
In Source Reading - A simple example (1), we learned that Observable.create (ObservableOnSubscribe<T> source) is actually the following code:
// ObservableCreate observableCreate = new ObservableCreate<T>(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { // Execution in IO Thread e.onNext("hello"); e.onNext("world"); e.onComplete(); } });
- ObservableCreate contains a subscribeActual(observer) method that executes the observer.onSubscribe method passed into the observer, and indirectly calls the observer's onNext, onComplete, and so on.
ObservableCreate
public final class ObservableCreate<T> extends Observable<T> { final ObservableOnSubscribe<T> source; public ObservableCreate(ObservableOnSubscribe<T> source) { this.source = source; } @Override protected void subscribeActual(Observer<? super T> observer) { CreateEmitter<T> parent = new CreateEmitter<T>(observer); observer.onSubscribe(parent); try { source.subscribe(parent); } catch (Throwable ex) { Exceptions.throwIfFatal(ex); parent.onError(ex); } } // Omit some code... }
- The second line of the subscribeActual method calls the observer.onSubscribe(parent) of the incoming observer; the method; when the subscription occurs, the onSubscribe method of the observer is actively executed by the subscription thread;
- The fourth line of the subscribeActual method calls the observer.subscribe method of the incoming observer; in the subscribe method, the user sends data by calling the CreateEmitter.onNext method;
- CreateEmitter is the encapsulation of Observer passed in by ObservableCreate.subscribeActual (Observer<? Super T> observer) method;
- The purpose of CreateEmitter is that when a task is cancelled, its encapsulated observer can no longer be called back; the onNext method of the observer is called by the CreateEmitter.onNext method;
See the code for observable.subscribeOn(Schedulers.io()) below
Note:
ObservableEmitter is a reference to CreateEmitter and a further encapsulation of Observer.When CreateEmitter executes onNext, if the task is cancelled, the onNext method of Observer is no longer callback.
b,observable.subscribeOn(Schedulers.io())
Below we look at the subscribeOn(Scheduler scheduler) method of the Observable class
Observable.java
public final Observable<T> subscribeOn(Scheduler scheduler) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); // Generate an ObservableSubscribeOn object return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler)); }
- Continue ignoring RxJavaPlugins
- Finally, an ObservableSubscribeOn object is returned
Here Observable observable = observableCreate.subscribeOn(Schedulers.io()) code is actually
ObservableSubscribeOn observable = new ObservableSubscribeOn<T>(observableCreate, Schedulers.io())
- So observable.subscribeOn(Schedulers.io()) returns a reference to ObservableSubscribeOn
View ObservableSubscribeOn below
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> { final Scheduler scheduler; public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) { super(source); this.scheduler = scheduler; } @Override public void subscribeActual(final Observer<? super T> s) { final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s); s.onSubscribe(parent); parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent))); } // ...omit part of the code }
Take a look at the subscribeActual method in ObservableSubscribeOn
- In the second line of code for the subscribeActual method, the onSubscribe method passed into Observer is executed;
- Line 3 of subscribeActual method: In the IO thread corresponding to the scheduler, execute the subscribe method of observableCreate, and the passed in parameter is SubscribeOnObserver, that is, execute observableCreate.subscribe (new SubscribeOnObserver) in the IO thread;
Therefore, regardless of which thread ObservableSubscribeOn.subscribeActual(observer) is called observableCreate.subscribe (new SubscribeOnObserver<T> (observer)) is executed in the IO thread, so e.onNext ("hello") for the observer; e.onComplete (); is also executed in the IO thread;
c,observable.observeOn(AndroidSchedulers.mainThread())
Below we look at the observeOn(Scheduler scheduler) method of the Observable class
public final Observable<T> observeOn(Scheduler scheduler) { return observeOn(scheduler, false, bufferSize()); } // public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize)); }
Here you can see that Observable observable = observableSubscribeOn.observeOn (Android Schedulers.mainThread()) is actually:
ObservableObserveOn observable = new ObservableObserveOn<T>(observableSubscribeOn, AndroidSchedulers.mainThread(), false, 128);
Therefore, observable.observeOn(AndroidSchedulers.mainThread()) returns a reference to ObservableObserveOn.
View ObservableObserveOn below
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> { final Scheduler scheduler; final boolean delayError; final int bufferSize; public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) { super(source); this.scheduler = scheduler; this.delayError = delayError; this.bufferSize = bufferSize; } @Override protected void subscribeActual(Observer<? super T> observer) { if (scheduler instanceof TrampolineScheduler) { source.subscribe(observer); } else { Scheduler.Worker w = scheduler.createWorker(); source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); } } // ...omit part of the code }
Take a look at the subscribeActual method in ObservableObserveOn
- The fifth line of code for the subscribeActual method is actually observableSubscribeOn.subscribe (new ObserveOnObserver <T> (observer, w, delayError, bufferSize));
- The purpose of ObserveOnObserver is to post the onNext method of ObserveOnObserver to the main thread of Android when the onNext method of ObserveOnObserver is implemented.
d,observable.subscribe(observer)
- We know that Observable's subscribe (Observer<? Super T> observer) method actually calls Observable's subscribeActual (Observer<? Super T> observer) method;
- The observable here is actually a reference to ObservableObserveOn;
Therefore, observable.subscribe(observer) actually executes observableObserveOn.subscribeActual(observer)
Here, our small example of thread switching (2) is transformed into the following code:
// Create an observer Observer observer = new Observer<String>() { @Override public void onSubscribe(@NonNull Disposable d) { // The moment the subscription thread subscribes, it executes in the subscription thread } @Override public void onNext(String o) { // Execute in Android main thread } @Override public void onError(@NonNull Throwable e) { // Execute in Android main thread } @Override public void onComplete() { // Execute in Android main thread } }; // ObservableCreate observableCreate = new ObservableCreate<T>(new ObservableOnSubscribe() { @Override public void subscribe(@NonNull ObservableEmitter e) throws Exception { // Execution in IO Thread e.onNext("hello"); e.onNext("world"); e.onComplete(); } }); // ObservableSubscribeOn observableSubscribeOn = new ObservableSubscribeOn<T>(observableCreate, Schedulers.io()) // ObservableObserveOn observableObserveOn = new ObservableObserveOn<T>(observableSubscribeOn, AndroidSchedulers.mainThread(), false, 128); // observableObserveOn.subscribeActual(observer);
Below we look at observableObserveOn.subscribeActual(observer)
ObservableObserveOn.java
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> { final Scheduler scheduler; final boolean delayError; final int bufferSize; public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) { // source is observableSubscribeOn super(source); // scheduler is Android Schedulers.mainThread() this.scheduler = scheduler; // false this.delayError = delayError; // 128 this.bufferSize = bufferSize; } @Override protected void subscribeActual(Observer<? super T> observer) { // AndroidSchedulers.mainThread() is Handler Scheduler, so you go to the else part of the code if (scheduler instanceof TrampolineScheduler) { source.subscribe(observer); } // The code goes to the else section else { Scheduler.Worker w = scheduler.createWorker(); // source is observableSubscribeOn source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); } } // ...omit part of the code }
- In the subscribeActual method, AndroidSchedulers.mainThread() is a Handler Scheduler, so the judgment statement in if is ignored and goes directly to the else part of the code.
- In the subscribeActual method, the observer observer is encapsulated as ObserveOnObserver; and the observableSubscribeOn.subscribe (new ObserveOnObserver<T> (observer, w, delayError, bufferSize)) is called.
- ObservableSubscribeOn.subscribe (new ObserveOnObserver <T> (observer, w, delayError, bufferSize)) is actually
ObserveOnObserver observeOnObserver = new ObserveOnObserver<T>(observer, w, delayError, bufferSize) // 1.'In Subscription Thread'- Executes onSubscribe, actually executes the observer's onSubscribe method observeOnObserver.onSubscribe(new SubscribeOnObserver<T>(observeOnObserver)); // 2.'In IO process'- Execute subscribe; In IO thread subscribe method, the user actively calls onNext, onError, onComplete methods of ObserveOnObserver to send data out observableCreate.subscribe(new SubscribeOnObserver<T>(observeOnObserver))
- User calls onNext of SubscribeOnObserver to send data
- SubscribeOnObserver.onNext calls observeOnObserver.onNext
- ObeOnObserver.onNext Posts methods such as observer.onNext, observer.onError, observer.onComplete to the Android main thread through Handler Scheduler to execute.
e. The overall flowchart is as follows
Finally, summarize the entire execution process of RxJava2:
Reference resources
Hand-on instructions for using RxJava 2.0 (1)
RxJava2 Source Parsing (1)
RxJava2 Source Parsing-Process