RxJava bit by bit (three #operator#)

This article will analyze the common operators in RxJava2.


· just

The role of just is to emit parameters in turn, and there are many overloaded methods


Except for the single parameter, other methods will call fromArray, which will be described later.

        The just single-argument method returns an ObservableJust object:

public final class ObservableJust<T> extends Observable<T> implements ScalarCallable<T> {
    private final T value;

    public ObservableJust(T value) {
        this.value = value;
    }

    protected void subscribeActual(Observer<? super T> s) {
        ScalarDisposable sd = new ScalarDisposable(s, this.value);
        s.onSubscribe(sd);
        sd.run();
    }

    public T call() {
        return this.value;
    }
}

        The logic of ObservableJust is very clear, we only need to care about the run() method of ScalarDisposable.

public static final class ScalarDisposable<T> extends AtomicInteger implements QueueDisposable<T>, Runnable {

    /* omit part of the code */

    final Observer<? super T> observer;
    final T value;

    public ScalarDisposable(Observer<? super T> observer, T value) {
        this.observer = observer;
        this.value = value;
    }

    public void run() {
        if(this.get() == 0 && this.compareAndSet(0, 2)) {
            this.observer.onNext(this.value);
            if(this.get() == 2) {
                this.lazySet(3);
                this.observer.onComplete();
            }
        }
    }
}

        The logic of ScalarDisposable here is also very clear, that is, the upstream onNext event is handed over to the Observer's onNext method for processing. Completed the RxJava call.


· fromArray

        The just method with multiple parameters mentioned above will call the fromArray method, taking two parameters as an example:

public static <T> Observable<T> just(T item1, T item2) {
        ObjectHelper.requireNonNull(item1, "The first item is null");
        ObjectHelper.requireNonNull(item2, "The second item is null");
        return fromArray(new Object[]{item1, item2});
}

        The same is true for more parameters, which will convert the parameters into arrays and pass them to the fromArray method. And fromArray will return ObservableFromArray object, look at ObservableFromArray to know the specific implementation:

public final class ObservableFromArray<T> extends Observable<T> {

    /* omit part of the code */

    final T[] array;

    public ObservableFromArray(T[] array) {
        this.array = array;
    }

    public void subscribeActual(Observer<? super T> s) {
        ObservableFromArray.FromArrayDisposable d = new ObservableFromArray.FromArrayDisposable(s, this.array);
        s.onSubscribe(d);
        if(!d.fusionMode) {
            d.run();
        }
    }

    static final class FromArrayDisposable<T> extends BasicQueueDisposable<T> {
        final Observer<? super T> actual;
        final T[] array;
        int index;
        boolean fusionMode;
        volatile boolean disposed;

        FromArrayDisposable(Observer<? super T> actual, T[] array) {
            this.actual = actual;
            this.array = array;
        }

        void run() {
            Object[] a = this.array;
            int n = a.length;

            for(int i = 0; i < n && !this.isDisposed(); ++i) {
                Object value = a[i];
                if(value == null) {
                    this.actual.onError(new NullPointerException("The " + i + "th element is null"));
                    return;
                }

                this.actual.onNext(value);
            }

            if(!this.isDisposed()) {
                this.actual.onComplete();
            }
        }
    }
}
The subscribeActual method will be executed to the run method of FromArrayDisposable. Then traverse the array passed in fromArray, if the event flow is not stopped, hand over the objects in the array to the onNext method of Observer for processing.


· map

The role of the map is to convert the upstream object into another object and then pass it to the downstream. It sounds a bit pale, but it is still demonstrated by code:

Observable
                .just(Integer.valueOf(1))
                .map(new Function<Object, Object>() {
                    @Override
                    public Object apply(@NonNull Object o) throws Exception {
                        return String.valueOf(o);
                    }
                })
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {
                    }

                    @Override
                    public void onNext(Object s) {
                        Log.d("rxrx", "onNext:" + s);
                        Log.d("rxrx", "onNext:" + s.getClass());
                    }

                    @Override
                    public void onError(Throwable throwable) {
                    }

                    @Override
                    public void onComplete() {
                    }
                });
04-25 09:55:43.620 24606-24606/com.newhongbin.lalala D/rxrx:onNext:1
04-25 09:55:43.620 24606-24606/com.newhongbin.lalala D/rxrx: onNext:class java.lang.String

Combining with the log, it can be seen that the Integer sent from the upstream becomes a String when it reaches the downstream, and this transformation process is implemented in the map. The implementation principle is also relatively simple. Call the apply method in the Observable to return the converted object, and then hand it over to the Observer's onNext method for processing.


· flatMap、concatMap、switchMap

        flatMap, concatMap, and switchMap all play the same transformation role as map, but their transformed objects are all implementation classes of ObservableSource, and upstream events are packaged into implementation classes of ObservableSource and then associated with Observer. Before the transformation, there is 1 observed person and N events, and after the transformation, it becomes N observed persons.

        The difference between the three:

        flatMap: emit events out of order.

        concatMap: Events are ordered, consistent with the upstream order.

        switchMap: If the previous event is not emitted, it will be discarded and the current latest event will be emitted.

If the upstream transmits "1", "2", "3", "4", "5" respectively with a delay, the implementation of the Observer after these three transformations are as follows:

        flatMap: Because of out-of-order emission, the execution situation is not necessarily.

        concatMap: emit in order, execute "1", "2", "3", "4", "5" in order.

        switchMap: When a new event arrives, the previous one has not been emitted, so the latest one is emitted, and only "5" is executed in the end.


· buffer

        The buffer is used to control the number of processing by the Observer at a time, combined with the example:

Observable
                .just(1,2,3,4,5,6,7,8,9,10)
                .buffer(3, 3)
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {
                        Log.d("rxrx", "onSubscribe:");
                    }

                    @Override
                    public void onNext(Object s) {
                        Log.d("rxrx", "onNext:" + s);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                    }

                    @Override
                    public void onComplete() {
                    }
                });
04-25 14:17:30.532 32283-32283/com.newhongbin.lalala D/rxrx: onSubscribe:
04-25 14:17:30.532 32283-32283/com.newhongbin.lalala D/rxrx:onNext:[1, 2, 3]
04-25 14:17:30.532 32283-32283/com.newhongbin.lalala D/rxrx:onNext:[4, 5, 6]
04-25 14:17:30.532 32283-32283/com.newhongbin.lalala D/rxrx:onNext:[7, 8, 9]
04-25 14:17:30.532 32283-32283/com.newhongbin.lalala D/rxrx:onNext:[10]

        The upstream transmits 10 events in sequence, and the downstream Observer processes the number of events specified by the buffer each time, and processes the insufficient ones at one time. The first parameter indicates the number of events to process at one time, and the second parameter indicates how many events to skip the next time the event is processed. When the two parameters are the same, Observer will be wrapped into BufferExactObserver, look at the four methods of BufferExactObserver:

public void onSubscribe(Disposable s) {
    if(DisposableHelper.validate(this.s, s)) {
        this.s = s;
        this.actual.onSubscribe(this);
    }
}

public void onNext(T t) {
    Collection b = this.buffer;
    if(b != null) {
        b.add(t);
        if(++this.size >= this.count) {
            this.actual.onNext(b);
            this.size = 0;
            this.createBuffer();
        }
    }
}

public void onError(Throwable t) {
    this.buffer = null;
    this.actual.onError(t);
}

public void onComplete() {
    Collection b = this.buffer;
    this.buffer = null;
    if(b != null && !b.isEmpty()) {
        this.actual.onNext(b);
    }

    this.actual.onComplete();
}

When the event is sent to onNext, it is not immediately handed over to the Observer for processing, but is placed in a collection. When the number of collections reaches our limit value, the entire collection will be handed over to the Observer's onNext for processing. Finally, after all events are sent, onComplete is called. If there are still events in the collection that have not been processed at this time, the collection is first handed over to the Observer's onNext for processing, and then the Observer's onComplete method is executed.

        The buffer has a lot of overloaded methods, which support a variety of ways to specify the number, such as:

public final Observable<List<T>> buffer(long timespan, TimeUnit unit) {
        return this.buffer(timespan, unit, Schedulers.computation(), 2147483647);
}

        This method can specify the event that the Observer emits per processing unit time.


· zip

        The function of zip is to combine the events emitted by multiple Observables and combine them into one object and pass it to the downstream.


. . . Not finished, there are too many operators, write slowly








Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324926430&siteId=291194637
Bit
BIT