RxJava2進階教程(一)——建立型操作符

Knight_Davion發表於2017-08-02

寫在前面的話:RxJava的強大之處不僅在於它的設計思想,更是因為有著各種強大的操作符,操作符讓你可以靈活的處理變換、組合、操縱和處理Observable發射的資料,接下來的幾篇文章會按照操作符的分類逐步講解各個操作符的作用,合理使用這些操作符也許你會達到事半功倍的效果。
本文適用於那些RxJava的初學者進階使用,但是如果你還不知道什麼是RxJava,那麼我只能說

這篇的主題是建立型操作符,也就是建立Observable的操作符,先來看看都有那些操作符吧:

  1. create()
  2. from()
  3. just()
  4. interval()
  5. timer()
  6. empty()
  7. error()
  8. range()
  9. repeat()
  10. defer()
  11. never()

1.Create

這個就沒什麼好說的了吧?大多數時候我們都是用這個函式來建立Observable的,
經典的流試呼叫

Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            if (!e.isDisposed()) {
                e.onNext(1);
            }
        }
    }).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
        }
    });複製程式碼

2.from

from的作用是將一個Iterable, 一個Future, 或者一個陣列轉換成一個Observable,from方法具體有一下幾種:


常用的有frmoArray和fromIterable這兩個,來看個具體例子吧
集合遍歷

  List<Integer> ls = new ArrayList<>();
    ls.add(1);
    ls.add(2);
    ls.add(3);
    Observable.fromIterable(ls).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept: " + integer);
        }
    });複製程式碼

其他的方法大家自行體會吧

3.just

just是將一個或多個物件轉換成發射這個或這些物件的一個Observable,在某些情況下它其實和from的作用有些類似,或者你也可以理解為這是一個簡版的create方法。來看具體例子:

Observable.just(1).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept: "+integer);
        }
    });複製程式碼

just可以傳入一個或多個物件,然後一次發射出來,對於資料量較小時可以使用這個方法。

4.interval

interval可以建立一個按照給定的時間間隔發射整數序列的Observable,通常我們可以用它來來完成一些週期行的操作,比如心跳,Handler最好的替代品了,來看具體例子:

 Observable.interval(2, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
        @Override
        public void accept(@NonNull Long aLong) throws Exception {
            Log.i(TAG, "accept: "+aLong);
        }
    });複製程式碼

第一個引數為時間間隔,第二個為時間單位,上述accept()會2S執行一次,在這裡你就可以完成一些週期性任務了。

5.timer

timer可以建立一個在給定的延時之後發射單個資料的Observable,通常可以用它完成一些定時任務,注意它和interval的區別,interval是週期性的(多次),timer是定時的(一次),具體例子:

Observable.timer(5, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
        @Override
        public void accept(@NonNull Long aLong) throws Exception {
            Log.i(TAG, "accept: "+aLong);
        }
    });複製程式碼

引數和interval一樣,5s之後執行accept方法

6.empty

empty可以建立一個什麼都不做直接通知完成的Observable。這個操作符的使用範圍就比較窄了,舉一個應用場景,我們做資料快取時通常的實現邏輯是先載入本地快取,如果本地沒有或者已經過期那麼才請求網路,這裡就可以使用empty,假設背地快取不存在,那麼是丟擲異常還是返回null呢?顯然這兩種都不合理,因為如果本地不存在我們需要直接請求網路,一種解決辦法就是當為空的時候直接返回Observable.empty(),同時藉助switchIfEmpty(observable1,observable2)方法完成後續的網路請求。當然你也可以通過concat和first來完成資料的獲取,這是我們後續的文章要說的了。場景說忘了,那到底是不是直接通知完成呢?測試一下就知道了

   Observable<Integer> o1 = Observable.empty();
    o1.subscribe(new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {
        }
        @Override
        public void onNext(Integer integer) {
            Log.i(TAG, "onNext: ");
        }
        @Override
        public void onError(Throwable e) {
            Log.i(TAG, "onError: ");
        }
        @Override
        public void onComplete() {
            Log.i(TAG, "onComplete: ");
        }
    });複製程式碼


果然是隻有onComplete執行了。

7.error

error可以建立一個不發射資料以一個錯誤終止的Observable,需要一個Throwable引數,使用場景還是拿快取舉例,比如記憶體快取不存在,網路資料也請求失敗了,那麼我們就可以呼叫這個操作符丟擲一個Throwable。那麼就直接執行到了Observer的onError方法裡裡。測試一下,上面的例子不變,我們把empty換成error,並隨便傳入一個Throwable:

Observable<Integer> o1 = Observable.error(new IOException());
    o1.subscribe(new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {
        }
        @Override
        public void onNext(Integer integer) {
            Log.i(TAG, "onNext: ");
        }
        @Override
        public void onError(Throwable e) {
            Log.i(TAG, "onError: ");
        }
        @Override
        public void onComplete() {
            Log.i(TAG, "onComplete: ");
        }
    });複製程式碼


直接執行了onError方法。

8.range

range可以建立一個發射指定範圍的整數序列的Observable。直接上例子:

Observable.range(0,5).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept: "+integer);
        }
    });複製程式碼

第一個引數為數列的起始元素,第二個為長度,列印結果為:


需要注意的是如果你將第二個引數設為0,將導致Observable不發射任何資料(如果設定為負數,會拋異常)

9. repeat

repeat可以建立一個重複發射指定資料的Observable,你也可以通過repeat(n)指定重複次數。更多時候我們會使用repeat(n)這個方法,具體例子:

 Observable.just(1).repeat(5).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept: "+integer);
        }
    });複製程式碼

結果為:

10.defer

defer的作用是隻有當Observer訂閱才建立Observable並且是為每個Observer建立一個新的Observable
正常情況下:

    int a = 10;
    Observable<Integer> o2 = Observable.just(a);
    a = 20;
    o2.subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept= " + integer);
        }
    });複製程式碼

輸出為accept=10,但是如果用defer

Observable<Integer> o1 = Observable.defer(new Callable<ObservableSource<Integer>>() {
        @Override
        public ObservableSource<Integer> call() throws Exception {
            return Observable.just(a);
        }
    });
    a = 20;
    o1.subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.i(TAG, "accept:= " + integer);
        }
    });複製程式碼

輸出為accept=20,大家仔細看一下上邊兩個例子就理解defer了。

11. never

never可以建立一個不發射資料也不終止的Observable,具體還沒有使用過,也沒想到應用場景大家知道有這麼一個操作符就可以了。

以上就是Observable的常見的建立操作符了,有遺漏的歡迎大家補充,下一篇會介紹常見的變換操作符,敬請期待。

相關文章