Rxjava(三)、操作符的使用

Android進階系列之第三方庫知識點整理。

知識點總結,整理也是學習的過程,如有錯誤,歡迎批評指出。

第一篇:Rxjava2(一)、基礎概念及使用
第二篇:Rxjava2(二)、五種觀察者模式及背壓

終於到操作符了,我覺得rxjava2如此好用,絕對少不了操作符的功勞,下面這張圖你就簡單的掃一眼,別慌,我們慢慢啃。

上一篇講了,rxjava有五種觀察者創建模式,其中ObservableFlowable差不多,只是Flowable支持背壓,而其它三種,都是簡化版的Observable,所以,本篇以Observable方式來講操作符的使用。

Observable源碼

Observable是一個抽象類,繼承ObservableSource

ObservableSource

一、創建操作符

這類操作符,創建直接返回Observable

1.1、嵌套回調事件

1.1.1、create

create是最常用的一個操作符,該操作符的參數中產生的emitter發射器,通過onNext不斷給下游發送數據,也可以發送onCompleteonError事件給下游。

需要發送給下游的數據,就通過emitter.onNext()給下游發送。

當發送了onComplete或者onError事件後,下游停止接收剩下的onNext事件

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RiA67RuB-1585813744640)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/create.png)]

方法:

static <T> Observable<T> create(ObservableOnSubscribe<T> source)

demo:

  Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("A");
                emitter.onNext("B");
                // .....
                emitter.onComplete();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

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

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

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

結果:

1.2、複雜數據遍歷

這類操作符,直接將一個數組集合拆分成單個ObJect數據依次發送給下游,也可以直接發送Object數據。

1.2.1、just

轉換一個或多個 Object 數據,依次將這些數據發射到下游。

最多接收十個Object參數。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LkOwj266-1585813744643)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/just.item.png)]

方法:

A : 最多隻接收十個參數。

Demo:

        Observable.just("A", "B", "C", "D")
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, "accept: s=" + s);
                    }
                });

結果:

1.2.2、fromArray

直接傳入一個數組數據,操作符將數組裏面的元素按先後順序依次發送給下游,可以發送十個以上的數據。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DCRxFkVB-1585813744647)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/from.png)]

方法:

static <T> Observable<T> fromArray(T... items)

Demo:

String[] data = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"};
        Observable.fromArray(data)
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, "fromArray--accept: s=" + s
                        );
                    }
                });

結果:

1.2.3、fromIterable

直接傳入一個集合數據,操作符將集合裏面的元素按先後順序依次發送給下游,可以發送十個以上的數據。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XR31LkKj-1585813744650)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/fromIterable.png)]

方法:

static <T> Observable<T> fromIterable(Iterable<? extends T> source)

Demo:

        List<String> mData = new ArrayList<>();
        mData.add("A");
        mData.add("B");
        mData.add("C");
        Observable.fromIterable(mData)
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, "fromIterable--accept: s=" + s);
                    }
                });

結果:

1.2.4、range

快速創建一個被觀察者對象,連續發送一個指定開始和總數的事件序列

立即發送,無延時

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1jdHM5Tj-1585813744653)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/range.png)]

方法:

static Observable<Integer> range(final int start, final int count)

Demo:

        // 從3開始發送,直到發送了十個數據停止。
        Observable.range(3, 10).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d(TAG, "range--accept: integer=" + integer);
            }
        });

結果:

1.3、定時任務

1.3.1、interval

快速創建一個被觀察者,延遲一定時間後再每隔指定的一個時間發送一個事件(從0開始的整數)給下游。

發送數據從0開始,依次+1整數遞增

延遲時間可以爲0,重載方法不設置默認使用第二個參數數值。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YrTlDMCm-1585813744659)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/timer.p.png)]

方法:

// initialDelay:發射第一個值需要等待時間
// period:後續每隔多少秒發射一個值
// unit:前兩個參數的時間單位
Observable<Long> interval(long initialDelay, long period, TimeUnit unit)
    
// 兩參方法
public static Observable<Long> interval(long period, TimeUnit unit) {
   	// 第一個參數和第二個參數一致,即延遲period後再每隔period秒發送一個事件。
    // 默認使用 Schedulers.computation()
    return interval(period, period, unit, Schedulers.computation());
 }

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-kzOuEYnd-1585813744660)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/timer.ps.png)]

方法:

// initialDelay:發射第一個值需要等待時間
// period:後續每隔多少秒發射一個值
// unit:前兩個參數的時間單位
// scheduler:等待發生併發出項目的調度程序
static Observable<Long> interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler)

demo:

// 延遲2秒後發送一個事件,後續每隔五秒發送一個事件
Observable.interval(2, 5, TimeUnit.SECONDS)
        .subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Long aLong) {
                Log.d(TAG, "onNext: aLong=" + aLong);
            }

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

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete: ");
            }
        });
1.3.2、intervalRange

快速創建1個被觀察者對象,每隔指定時間發送1個事件,可以指定事件發送開始的值和總的值。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iJEeWaFv-1585813744661)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/intervalRange.s.png)]

方法:

// start:範圍起始值
// count:要發出的值的總數,如果爲零,則操作員在初始延遲後發出onComplete。
// initialDelay:發出第一個值(開始)之前的初始延遲
// period:後續值之間的時間段
// unit:前面時間參數單位
static Observable<Long> intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit, Scheduler scheduler)

demo:

// 第一個延遲三秒後發送int值2,後續每隔1秒累加發送給下游,一共發送10個數據。
Observable.intervalRange(2, 10, 3, 1, TimeUnit.SECONDS)
        .subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Long aLong) {
                Log.d(TAG, "onNext: aLong=" + aLong);
            }

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

            @Override
            public void onComplete() {
                Log.d(TAG, "onComplete: ");
            }
        });

1.4、延遲任務

1.4.1、defer

創建一個Observable對象,被觀察者邏輯真正執行的時機是在其被訂閱的時候。

當下遊訂閱後,上游纔開始處理邏輯。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tQzeefmm-1585813744662)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/defer.png)]

方法:

// 
static <T> Observable<T> defer(Callable<? extends ObservableSource<? extends T>> supplier)

demo:

String[] mStrings = new String[]{"A", "B", "C", "D"};

Observable observable = Observable.defer(new Callable<ObservableSource<String>>() {
    @Override
    public ObservableSource<String> call() throws Exception {
        // 上游發送mStrings數組
        return Observable.fromArray(mStrings);
    }
});
// 在訂閱之前,將數組數據改變
mStrings = new String[]{"defer,訂閱時候才創建"};
// 訂閱
observable.subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        Log.d(TAG, "accept: s=" + s);
    }
});
1.4.2、timer

創建一個被觀察者對象,上游延時指定的時間後發送一個事件到下游。

發送的數值爲Long型的0

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-orS4Bv4E-1585813744663)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/timer.s.png)]

方法:

// delay:發射單個數據之前的延時
// unit:前者時間單位
// scheduler:指定的調度程序 (默認爲Schedulers.computation())
static Observable<Long> timer(long delay, TimeUnit unit, Scheduler scheduler) 

demo:

public void timer() {
        // 延遲5秒後發送Long型值0到下游,可指定Schedulers,默認Schedulers.computation()
        Observable.timer(5, TimeUnit.SECONDS)
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Log.d(TAG, "accept: aLong=" + aLong);
                    }
                });
    }

結果:

二、變換操作符

2.1、變換

2.1.1、map

對上游發送的每一個事件都進行指定的函數處理,從而變換成另一個事件再發送給下游。

常使用場景:用作數據類型轉換

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rKAyod61-1585813744667)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/map.png)]

方法:

// R:輸出類型
// mapper:應用於ObservableSource發出的每個項目的函數
final <R> Observable<R> map(Function<? super T, ? extends R> mapper)

demo:

    public void map() {
        // 通過just發送整型數值1、2、3
        Observable.just(1, 2, 3).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                // 通過Map操作符對上游的數據進行函數處理,再轉換成指定的事件發送給下游
                return integer + "變換";
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "accept: s=" + s);
            }
        });
    }
2.1.2、flatMap

將一個發送事件的上游Observable變換爲多個發送事件的Observables,然後將它們發射的事件單獨做處理後再合併放進一個單獨的Observable裏發送給下游。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OAQxt9EO-1585813744670)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/flatMap.png)]

可以看到上游發送了三個事件(注意顏色),中間對每個事假數據進行處理後(每一個圓變成兩個矩形),再合併成包含六個矩形事件的Observable對象發送給下游,注意矩形顏色,他是無規律,無序的,並不是嚴格按照上游發送的順序來發送給下游。

方法:

final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)

demo:

public void flatMap() {
    // 被觀察者通過just發送整型數值1、2、3
   Observable.just(1, 2, 3).flatMap(new Function<Integer, ObservableSource<String>>() {
        @Override
        public ObservableSource<String> apply(Integer integer) throws Exception {
            // 對收到的數值再進行函數處理。
            final List<String> list = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                list.add("變換後的數據" + integer);
            }
            // 將函數處理後的數據,在包裝成一個Observable對象發送給下游。
            return Observable.fromIterable(list).delay(10, TimeUnit.MILLISECONDS);
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d(TAG, "accept: s=" + s);
        }
    });
}
2.1.3、concatMap

flatMap一樣的功能,只是flatMap不能保證轉換後發送給下游事件的時序,concatMap轉換後能嚴格按照上游發送的順序再發送給下游。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2e8KeTa8-1585813744671)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatMap.png)]

flatMap一樣,重點注意顏色,轉換後顏色和上游發送的順序一致,有序發送

方法:

final <R> Observable<R> concatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, int prefetch)

demo:

public void concatMap() {
    // 被觀察者通過just發送整型數值1、2、3
    Observable.just(1, 2, 3).concatMap(new Function<Integer, ObservableSource<String>>() {
        @Override
        public ObservableSource<String> apply(Integer integer) throws Exception {
            // 對收到的數值再進行函數處理。
            final List<String> list = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                list.add("變換後的數據" + integer);
            }
            // 將函數處理後的數據,在包裝成一個Observable對象發送給下游。
            return Observable.fromIterable(list).delay(10, TimeUnit.MILLISECONDS);
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d(TAG, "accept: s=" + s);
        }
    });
}

三、合併操作符

3.1、concat

組合多個被觀察者一起發送數據,合併後 按發送順序串行執行

組合的被觀察者數量要求小於等於4個,從提供的方法參數裏面可以得知。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-g1TTreEw-1585813744673)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concat.png)]

方法:

public static <T> Observable<T> concat(
            ObservableSource<? extends T> source1, ObservableSource<? extends T> source2,
            ObservableSource<? extends T> source3, ObservableSource<? extends T> source4)

demo:

    public void concat() {
        // 用just操作符創建三個Observable對象
        Observable<String> observable1 = Observable.just("1", "2");
        Observable<String> observable2 = Observable.just("A", "B", "C");
        Observable<String> observable3 = Observable.just("hello", "rxjava");
        // 使用concat操作符合並三個Observable對象,並將合併後的數據順序(串行)發送給下游
        Observable.concat(observable1
                , observable2, observable3)
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, "accept: s=" + s);
                    }
                });
    }
3.2、concatArray

concat一樣,組合多個被觀察者一起發送數據,合併後 按發送順序串行執行

concatArray對組合的被觀察者對象沒有個數限制,可以大於4個。

示意圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rxUVWmQX-1585813744674)(https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/concatArray.png)]

上游發送的是一個組合的觀察者數組,沒有數量限制(注意顏色)

轉換後串行發送(顏色和上游發送順序對應)

方法:

static <T> Observable<T> concatArray(ObservableSource<? extends T>... sources) 

demo:

public void concatArray() {
    Observable<String> observable1 = Observable.just("1", "2");
    Observable<String> observable2 = Observable.just("A", "B", "C");
    Observable<String> observable3 = Observable.just("D", "E");
    Observable<String> observable4 = Observable.just("F");
    Observable<String> observable5 = Observable.just("G");
    Observable.concatArray(observable1, observable2, observable3, observable4, observable5)
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d(TAG, "accept: s=" + s);
                }
            });
}
3.3、concatDelayError、concatArrayDelayError

使用concat操作符時,如果遇到其中一個被觀察者發出onError事件則會馬上終止其他被觀察者的事件,如果希望onError事件推遲到其他被觀察者都結束後才觸發,可以使用對應的concatDelayError。

方法:

public static <T> Observable<T> concatDelayError(Iterable<? extends ObservableSource<? extends T>> sources) {
        ObjectHelper.requireNonNull(sources, "sources is null");
        return concatDelayError(fromIterable(sources));
    } 

public static <T> Observable<T> concatDelayError(ObservableSource<? extends ObservableSource<? extends T>> sources) {
        return concatDelayError(sources, bufferSize(), true);
    }
    
public static <T> Observable<T> concatDelayError(ObservableSource<? extends ObservableSource<? extends T>> sources, int prefetch, boolean tillTheEnd)

demo:

    public void concatArrayDelayError() {

        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("A");
                emitter.onNext("B");
                emitter.onNext("C");
                emitter.onError(new NullPointerException(""));
                emitter.onNext("D");
            }
        });


 Observable.concatArrayDelayError(observable, Observable.just("E", "F"))
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe: ");
                    }

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

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

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete: ");
                    }
                });
    }

結果:

可以看到,第一個observable發送到c後,手動拋出一個錯誤,但是並滅有影響到Observable.just(“E”, “F”)的執行,我們依舊打印出了 E,F兩個參數後纔去執行我們手動拋出的NullPointerException錯誤

。。。。

四、總結

操作符這部分內容比較多,先整理這部分,後面會對其他操作符再做整理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章