Rxjava (II)

Time:2022-5-15

1、 Observer mode

1.1. Traditional observer model

Rxjava (II)

1.2 observer mode of rxjava

Rxjava (II)

  • difference
    The traditional observer mode is one observable and multiple observers. The observer mode of rxjava is multiple observable and one observer.

2、 Subscription process

Let’s take this simple code as an example:

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
                //Publish event
                emitter.onNext(11);
                emitter.onComplete();
            }
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                  //Subscribe
            }

            @Override
            public void onNext(@NonNull Integer i) {
                  //Handling receive events
            }
            @Override
            public void onError(@NonNull Throwable e) { }
            @Override
            public void onComplete() {}
        });
    }

The general flow is shown in the following two figures

  • Important steps in the process of observable and observer subscription:

    Rxjava (II)

    Subscription process of observable and observer
  • Important steps in the subscription process of observable and observer (obsolete)

    Rxjava (II)

    Subscription process of observable and observer

2.1. Observable creation process

Rxjava (II)

We useObservableInsidecreateCreate an observer

        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(11);
                emitter.onComplete();
            }
        })
public interface ObservableOnSubscribe<T> {
    void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}

From the above, we can get that one will be created in the Create methodObservableOnSubscribeObject.
Let’s seeObservable#createmethod:

    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

aboveRxJavaPlugins.onAssembly()We don’t need to talk about it. It’s mainly usedHookTechnology, you can count the use of operators. See previous section.
Then we look directlyObservableCreateWhat to do:

public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        //Observableonsubscribe created by source for us
        this.source = source;
    }

    ...
}

ObservableCreateThe main thing inside is toObserverAfter subscription, it is packaged, processed and sent to the source. The specific process is shown below:

2.2 subscription process of observable and observer

Rxjava (II)

We fromObserverAs an entry point:

new Observer<Integer>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {}
            @Override
            public void onNext(@NonNull Integer i) {}
            @Override
            public void onError(@NonNull Throwable e) {}
            @Override
            public void onComplete() {}
        }

We callsubscribeWhen subscribing, the above createdObserverPass it in

subscribe(new Observer<Integer>() {
}

After execution toObservable#subscribemethod

//The parameter observer is the observer created above
    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
           //Check 
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
            //Subscribe to observers
            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;
        }
    }

implementObservableCreate#subscribeActual

@Override
    protected void subscribeActual(Observer<? super T> observer) {
        //To create an emitter is to wrap observer with a layer of baggage
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //Call the subscription in observer (onsubscribe)
        observer.onSubscribe(parent);

        try {
            //Source is the observableonsubscribe passed in when we created it above
            //Callback to create 'subscribe' in observable`
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

ObservableCreate#CreateEmitterholdObserverPackage when receivedObserableWhen sending events, handle them accordingly.

static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {
        //Ensure the consistency of versions
        private static final long serialVersionUID = -3434801548987643227L;
        //The observer we created above
        final Observer<? super T> observer;
        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;
        }

        @Override
        public void onNext(T t) {
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {
                //Return event
                observer.onNext(t);
            }
        }

        @Override
        public void onError(Throwable t) {
            if (!tryOnError(t)) {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public boolean tryOnError(Throwable t) {
            if (t == null) {
                t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
            }
            if (!isDisposed()) {
                try {
                    observer.onError(t);
                } finally {
                    dispose();
                }
                return true;
            }
            return false;
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    //Completion event
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

        @Override
        public void setDisposable(Disposable d) {
            DisposableHelper.set(this, d);
        }

        @Override
        public void setCancellable(Cancellable c) {
            setDisposable(new CancellableDisposable(c));
        }

        @Override
        public ObservableEmitter<T> serialize() {
            return new SerializedEmitter<T>(this);
        }

        @Override
        public void dispose() {
            DisposableHelper.dispose(this);
        }

        @Override
        public boolean isDisposed() {
            return DisposableHelper.isDisposed(get());
        }
    }

2.3 summary

Rxjava (II)

Overall flow chart

From the above figure, the rxjava subscription process is a U-shaped structure

2、 Map source code analysis

Rxjava (II)

Execution process

code

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(11);
                emitter.onComplete();
            }
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(@NonNull Integer integer) throws Exception {
                Return "convert to string:" + integer;
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) { }
            @Override
            public void onNext(@NonNull String s) { }
            @Override
            public void onError(@NonNull Throwable e) { }
            @Override
            public void onComplete() { }
        });

2.1 subscription process

The subscription process is analyzed according to the following flow chart:

Rxjava (II)

  • We skip the creation process of observable and observer and directly analyze the map creation and subscription process
.map(new Function<Integer, String>() {
            @Override
            public String apply(@NonNull Integer integer) throws Exception {
                Return "convert to string:" + integer;
            }
        })

belowFunctionThe function of is to return the input parameter t = = > to the value R, that is, integer = = > string type.

public interface Function<T, R> {
    R apply(@NonNull T t) throws Exception;
}

implementObservable#mapOperator:

public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        // this : Observable
        //Mapper: created function object 
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

Then againObservableMapThere are downstream subscriptionsObserverPackaged byObservable#subscribeMethod Jinxing processing

public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    final Function<? super T, ? extends U> function;

    public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
        //Source refers to the observable data transmitted from upstream
        super(source);
        this.function = function;
    }

    @Override
    public void subscribeActual(Observer<? super U> t) {
        //T is the downstream subscribed observer
        //Package observer into mapobserver
        //   source. Subscribe() will call the subscribe method of observable to subscribe to the upper layer
        source.subscribe(new MapObserver<T, U>(t, function));
    }

    static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
        final Function<? super T, ? extends U> mapper;

        MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
            super(actual);
            this.mapper = mapper;
        }

        @Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != NONE) {
                actual.onNext(null);
                return;
            }

            U v;

            try {
                v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
            } catch (Throwable ex) {
                fail(ex);
                return;
            }
            //Send events downstream
            actual.onNext(v);
        }

        @Override
        public int requestFusion(int mode) {
            return transitiveBoundaryFusion(mode);
        }

        @Nullable
        @Override
        public U poll() throws Exception {
            T t = qs.poll();
            return t != null ? ObjectHelper.<U>requireNonNull(mapper.apply(t), "The mapper function returned a null value.") : null;
        }
    }
}

Observable#subscribeSubscription processing

    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");

            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;
        }
    }

fromMapObserverParent class ofBasicFuseableObserverInsideonSubscribeMethod to process subscriptions.

public final void onSubscribe(Disposable s) {
        if (DisposableHelper.validate(this.s, s)) {
            this.s = s;
            if (s instanceof QueueDisposable) {
                this.qs = (QueueDisposable<T>)s;
            }
            if (beforeDownstream()) {
                //Subscribe to observers
                actual.onSubscribe(this);
                afterDownstream();
            }

        }
    }

The following is a simple diagram of the whole:

Rxjava (II)

  • summary
    thus it can be seenRxJavaOther operators andmapThe parsing process is the same, involving packet and unpacking.

3、 Rxjava decoration model

Rxjava takes advantage ofDecorative modelholdObservableThe package is as shown in the figure below:

Rxjava (II)

After packaging, execute to the bottom. Then execute the subscription, remove the previous packet, and then reObserverPacket, and then unpack again when sending the message, as shown in the figure below:

Rxjava (II)

Sequence diagram