The most easy-to-understand teaching you to use RxJava3 (2)

Terminology in Rxjava

1. Upstream and downstream

The data flow in RxJava includes a data source, 0 or more intermediate steps, a data consumer or combined sub-steps (the steps are responsible for using the data flow in a certain way):

source
  .operator1()
  .operator2()
  .operator3()
  .subscribe(consumer)

From the perspective of operator2, the source to the left is upstream , and the subscribe(consumer) to the right is downstream

2. The object of movement

In the RxJava documentation, emission, emits, item, event, signal, data and message are all synonyms, and they all mean objects that move along the data stream.

3. Back pressure

Using backpressure allows the current step to limit the memory usage of the data stream when it is generally impossible to know how many items of data will be sent upstream.
In RxJava, Flowableclasses are designed to support back pressure, and Observableclasses are dedicated to non-back pressure operations. Single, Maybe and Completable also do not support back pressure.

4. Schedulers

RxJava operators do not directly use Thread or ExecutorServices, but use the so-called Scheduler, which abstracts the concurrency source behind the unified API.
Scheduler usage type

  1. Schedulers.computation(): Run computationally intensive work on a fixed number of dedicated threads in the background. Most asynchronous operators use this as their default scheduler.
  2. Schedulers.io(): Run similar I/O or blocking operations on a group of dynamically changing threads.
  3. Schedulers.single(): Run work on a single thread in a sequential and FIFO manner.
  4. Schedulers.trampoline(): Run jobs in a sequential and FIFO manner in the participating threads, usually for testing purposes.
    Of course, certain platform also have other scheduling usage , such as the android system has an additional use:
    AndroidSchedulers.mainThread(), SwingScheduler.instance() or JavaFXSchedulers.gui().

You can also use a custom ExecutorService [^1] task scheduling service through the Scheduler .from(Executor) method . It will have a larger but still fixed thread pool (different from using compute() and io() separately).

Use of Observer and Observable in Rxjava

The main application scenario of the responsive programming library RxJava is asynchronous. Observer and Observable in
RxJava are two important classes or interfaces. Below we conduct a simple test.

(1) First create an instance of Observable.

  1. There are many creation methods, such as create(), defer(), just(), from(), rang(), timer(), interval(), etc. The most commonly used create is used here, and its parameter is an ObservableOnSubscribe instance.
  2. ObservableOnSubscribe#subscribe( ObservableEmitter emitter) will be called back at this time . The subscribe(ObservableEmitter emitter) will make a response callback when the Observable is subscribed, and its response is after the Observer#onSubscribe(Disposable d) method.
    private ObservableEmitter<String> mEmitter;
    private Observable<String> mObservable;

    private void createObservable() {
    
    
        mObservable = Observable.create(new ObservableOnSubscribe<String>() {
    
    
            @Override
            public void subscribe(ObservableEmitter<String> emitter) {
    
    
                Log.i(TAG, "  Observable  has  create");
                mEmitter = emitter;
            }
        });
    }

Calling createObservable() method subscribe(ObservableEmitter emitter) will not respond.

(2)
For a detailed explanation of the four methods of instantiating an Observer object Observer, please see Observer

    private Observer<String> mObserver = new Observer<String>() {
    
    
        @Override
        public void onSubscribe(Disposable d) {
    
    
            Log.i(TAG, "  +++ onSubscribe");
            if (d != null) {
    
    
                System.out.println("  d.hashCode()=" + d.hashCode() + "  mEmitter.hashCode() " + mEmitter.hashCode());
                System.out.println("  d.getClass()=" + d.getClass().getCanonicalName());
            }
        }

        @Override
        public void onNext(String s) {
    
    
            Log.i(TAG, "  +++ onNext" + s);
        }

        @Override
        public void onError(Throwable e) {
    
    
            Log.i(TAG, "  +++ onError");
        }

        @Override
        public void onComplete() {
    
    
            Log.i(TAG, "  +++ onComplete");
        }
    };

(3) Observable subscribes to
mObservable.subscribe(mObserver); it
should be noted that subscribe to subscribe(mObserver) multiple times, you will find

        public void onSubscribe(Disposable d) {
    
    
            Log.i(TAG, "  +++ onSubscribe");
            if (d != null) {
    
    
                System.out.println("  d.hashCode()=" + d.hashCode() + "  mEmitter.hashCode() " + mEmitter.hashCode());
                System.out.println("  d.getClass()=" + d.getClass().getCanonicalName());
            }
        }
  1. The observer.onSubscribe method is called before Observable.subscribe

I: +++ onSubscribe
I: d.hashCode()=464508421
I: d.getClass()=io.reactivex.internal.operators.observable.ObservableCreate.CreateEmitter
I: Observable has create

  1. d.getClass()=io.reactivex.internal.operators.observable.ObservableCreate.CreateEmitter knows that d in onSubscribe(Disposable d) is an Emitter class
  2. By calling mObservable.subscribe(mObserver) multiple times, check the print result as follows:

I/System.out: d.hashCode()=464508421
I/System.out: mEmitter.hashCode() 464508421
I/System.out: d.hashCode()=703714906
I/System.out: mEmitter.hashCode() 703714906
I/System.out: d.hashCode()=786686091
I/System.out: mEmitter.hashCode() 786686091

Every time mObservable.subscribe(mObserver) is called, there will be a new implementation subclass of Emitter and Disposable ( Disposable d and ObservableEmitter emitter hashCode are exactly the same ).
Explain that Observable.subscribe() will create a new ObservableEmitter every time .

(4)
After the observable changes the state of the Observable, the data is transmitted by the ObservableEmitter through the onNext, onComplete, and onError methods, and the subscribed Observer will respond to the corresponding onNext, onComplete, and onError methods. Such as execution method:

 mEmitter.onNext("Hello");
 mEmitter.onComplete();

The response sequence of the method is

ObservableEmitter.onNext
Observer.onNext
ObservableEmitter.onComplete
Observer.onComplete
and found that mEmitter.hashCode will not change

If you perform multiple mEmitter.onNext("Hello"); mEmitter.onComplete();operations,
there are only ObservableEmitter.onNext 、 ObservableEmitter.onCompletetwo ways to respond.
Observer.onNext 、 Observer.onCompleteWill not respond. This is verified. Observer will only respond once to the same state change.

Related links are as follows:

Guess you like

Origin blog.csdn.net/luo_boke/article/details/105579864