RxJava操作符(一)Creating Observables

RxJava只是ReactiveX(Reactive Extensions)的一種java實現, ReactiveX是一種響應式擴展框架,有很多種實現,如RxAndroid, RxJS, RxSwift, RxRuby等等。RX採用一種類似於觀察者的形式來實現各種功能,跟我們一般的寫代碼思路差別較大。剛開始接觸可能會覺得難以理解,但是一旦掌握地話就會體會到其強大之處。其原理就是創建一個Observable對象來幹活,然後使用各種操作符建立起來的鏈式操作,就如同流水線一樣把你想要處理的數據一步一步地加工成你想要的成品然後發射(emit)給Subscriber。

RxAndroid是對RxJava在Android上的擴展,如果你是做安卓開發的話,各種主線程和子線程的操作肯定會讓你覺得頭疼,RxAndroid可以很容易地解決你的這種困擾。爲了方便測試和編譯,本文的demo程序都是基於RxAdroid來實現的。

RX的強大就在其豐富的操作符,所以要靈活地使用RX的話就必須要掌握這些操作符,讓我們首先來看一下如何創建Observable的操作符。

一、Create

Create是最基本的創建Observable的操作符,其原理圖如下所示(本文中的原理圖都使用了官網的圖片)
create

創建一個Observable最重要的就是要和合適的時機調用Subscriber的onNext/onComplete/onError方法。onNext就是發射處理好的數據給Subscriber; onComplete用來告訴Subscriber所有的數據都已發射完畢;onError是在發生錯誤的時候發射一個Throwable對象給Subscriber。需要注意的一點就是Observable必須調用所有的Subscriber的onComplete方法並且只能調用一次,出錯的時候調用onError方法也是一樣的,並且一旦調用後就不能調用Subscriber的任何其他方法了。下面是Create操作符的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Observable<Integer> createObserver() {
        return Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                if (!subscriber.isUnsubscribed()) {
                    for (int i = 0; i < 5; i++) {
                        int temp = new Random().nextInt(10);
                        if (temp > 8) {
                            //if value>8, we make an error
                            subscriber.onError(new Throwable("value >8"));
                            break;
                        } else {
                            subscriber.onNext(temp);
                        }
                        // on error,complete the job
                        if (i == 4) {
                            subscriber.onCompleted();
                        }
                    }
                }
            }
        });
    }

在這個方法裏,我們創建並返回了個Observable,這個Observable會產生5個小於10的隨機數並且依次發射出去,如果隨機數大於8,我們就認爲是一個Error。下面是我們對這個Observable的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mLButton.setOnClickListener(e -> createObserver().subscribe(new Subscriber<Integer>() {
           @Override
           public void onCompleted() {
               log("onComplete!");
           }

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

           @Override
           public void onNext(Integer integer) {
               log("onNext:" + integer);
           }
       }));
   }

當點擊button的時候,我們就會建立一個Subscriber對象並將其註冊給創建的Observable對象,然後接收其發射來的數據。測試的時候共點擊了兩次,第一次順利發射完了5個數據,第二次在發射了2個數據後產生了錯誤。運行結果如下:

二、Range

Range操作符根據出入的初始值n和數目m發射一系列大於等於n的m個值

其使用也非常方便,僅僅制定初始值和數目就可以了,不用自己去實現對Subscriber的調用

1
2
3
private Observable<Integer> rangeObserver() {
        return Observable.range(10, 5);
}

對其訂閱:

1
mRButton.setOnClickListener(e -> rangeObserver().subscribe(i -> log(i)));

運行結果輸出了10-14的5個數:

三、Defer、Just

Defer操作符只有當有Subscriber來訂閱的時候纔會創建一個新的Observable對象,也就是說每次訂閱都會得到一個剛創建的最新的Observable對象,這可以確保Observable對象裏的數據是最新的,其特點我們將在下面和Just進行對比理解。

Just操作符將某個對象轉化爲Observable對象,並且將其發射出去,可以使一個數字、一個字符串、數組、Iterate對象等,是一種非常快捷的創建Observable對象的方法,在以後的例子裏會大量使用。

下面我們來分別使用defer和just創建一個Observable,來返回當前的毫秒數

1
2
3
4
5
6
7
private Observable<Long> DeferObserver() {
        return Observable.defer(() -> Observable.just(System.currentTimeMillis()));
    }
    
private Observable<Long> JustObserver() {
        return Observable.just(System.currentTimeMillis());
    }

分別對其訂閱:

1
2
mLButton.setOnClickListener(e -> deferObservable.subscribe(time -> log("defer:" + time)));
mRButton.setOnClickListener(e -> justObservable.subscribe(time -> log("just:" + time)));

好了,來看一下運行結果吧,可以看到使用Defer操作符創建Observable對象每次調用我們都可以得到最新的的當前時間,而使用just只會返回同一個時間。

四、From

From操作符用來將某個對象轉化爲Observable對象,並且依次將其內容發射出去。這個類似於just,但是just會將這個對象整個發射出去。比如說一個含有10個數字的數組,使用from就會發射10次,每次發射一個數字,而使用just會發射一次來將整個的數組發射出去。

使用from創建兩個Observable對象,來源分別是一個數組和list

1
2
3
4
5
6
7
private Observable<Integer> FromArray() {
    return Observable.from(arrays);
}

private Observable<Integer> FromIterable() {
    return Observable.from(list);
}

進行訂閱

1
2
mLButton.setOnClickListener(e -> FromArray().subscribe(i -> log("FromArray:" + i)));
mRButton.setOnClickListener(e -> FromIterable().subscribe(i -> log("FromIterable:" + i)));

運行結果如下,可以看到數組和list中的數據被依次地發射出來。

五、Interval

Interval所創建的Observable對象會從0開始,每隔固定的時間發射一個數字。需要注意的是這個對象是運行在computation Scheduler,所以如果需要在view中顯示結果,要在主線程中訂閱。

使用interval創建一個Observable對象,其間隔爲1秒鐘。

1
2
3
4
5
private Observable<Long> interval() {
    return Observable.interval(1, TimeUnit.SECONDS)
    //interva operates by default on the computation Scheduler,so observe on main Thread
    observeOn(AndroidSchedulers.mainThread());
}

進行訂閱和反訂閱,反訂閱後將不會再收到Observable發射來的數據。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Observable<Long> observable = interval();
Subscriber<Long> subscriber = new Subscriber<Long>() {
    @Override
    public void onCompleted() {
        log("onCompleted" );
    }

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

    @Override
    public void onNext(Long aLong) {
        log("interval:" + aLong);
    }

};
mLButton.setText("Interval");
mRButton.setText("UnSubsCribe");
mLButton.setOnClickListener(e -> observable.subscribe(subscriber));
mRButton.setOnClickListener(e -> subscriber.unsubscribe());

運行結果

六、Repeat、Timer

Repeat會將一個Observable對象重複發射,我們可以指定其發射的次數

Timer會在指定時間後發射一個數字0,注意其也是運行在computation Scheduler

分別使用Repeat和Timer創建一個Observable對象:

1
2
3
4
5
6
7
8
private Observable<Integer> repeatObserver() {
    return Observable.just(1).repeat(5);
}

private Observable<Long> timerObserver() {
    //timer by default operates on the computation Scheduler
    return Observable.timer(1, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread());
}

進行訂閱:

1
2
mLButton.setOnClickListener(e -> repeatObserver().subscribe(i -> log("repeat:" + i)));
mRButton.setOnClickListener(e -> timerObserver().subscribe(i -> log("timer:" + i)));

運行結果如下,可以看到Repeat創建的對象發射了5個1,Timer創建的對象在1秒鐘後發射了一個0。

創建操作符還有Nerver/Empty/Throw等,非常簡單但是我感覺可能用到的機會不多,就不細說了。

本文的demo程序見github

原文點擊打開鏈接

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