RxJava操作符之Creating Observables

ChuckChenLw發表於2016-06-23

  RxJava 是一個在Java虛擬機器上實現的響應式擴充套件庫:提供了基於observable序列實現的非同步呼叫及基於事件程式設計。 它擴充套件了觀察者模式,支援資料、事件序列並允許你合併序列,無需關心底層的執行緒處理、同步、執行緒安全、併發資料結構和非阻塞I/O處理。
  官網定義:RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.
  如果沒有接觸過響應式程式設計,看起來會難以理解。但是,一旦上手之後,你會發覺用起來很爽。在Android中可以使用RxAndroid輕鬆實現執行緒切換,輕鬆寫出優雅的程式碼。不過這都建立在熟練使用的基礎上的。
  本文不是講解RxJava的原理的,而是RxJava另一重要的內容,功能強大、豐富的操作符。
  將會以下分類用一系列的文章,介紹這些操作符
  1.Creating Observables
  2.Transforming Observables
  3.Filtering Observables
  4.Combining Observables
  5.Error Handling Operators
  6.Observable Utility Operators
  7.Conditional and Boolean Operators
  8.Mathematical and Aggregate Operators
  9.Connectable Observable Operators
  10.Backpressure Operators
  
  從Create Observables類操作符開始講起吧,顧名思義這類操作符都是可以得到Observable的。主要包括:
  1.Create
  2.Defer
  3.Empty/Never/Throw
  4.From
  5.Interval
  6.Just
  7.Range
  8.Repeat
  9.Timer

 create操作符
   create操作符是最基本的操作符,可以在合適的時機呼叫subscriber的onNext,onError,onComplete方法。下圖是官方給的create的原理圖(本系列所用的原理圖都是官方所給的):
 RxJava操作符之Creating Observables
  onNext就是發射資料給Subscriber; onComplete用來通知Subscriber所有的資料都已發射完畢;onError是在發生錯誤的時候發射一個Throwable物件給Subscriber。這裡要注意一下,Observable在需要呼叫OnComplete方法時,必須通知所有訂閱其的Subscriber,之後Observable將不再發射資料,OnError也是同樣的。接下來看看具體的程式碼,為了方便看程式碼,部分程式碼暫時沒有使用Lamda表示式:

private Observable<String> createObservable() {
        return Observable.create(subscriber -> {
            for (int i = 0; i < 5; i++) {
                int num = new Random().nextInt(10);
                if (!subscriber.isUnsubscribed()) {
                    if (num > 5 && num < 8) {
                        subscriber.onError(new Throwable());
                    } else if (num >= 8) {
                        subscriber.onCompleted();
                    }else {
                        subscriber.onNext(num+"");
                    }
                }
            }
        });
    }
btn_create.setOnClickListener(v1 -> createObservable()
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        Log.e("create", "onComplete");
                    }

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

                    @Override
                    public void onNext(String s) {
                        Log.e("create", s);
                    }
                }));

 執行結果

create: 4
create: 5
create: 0
create: 3
create: 1
create: 5
create: onError
create: 4
create: 4
create: 1
create: onComplete

  以上結果是執行了3次的結果,第一次順利執行,第二次觸發了onError後Observable就停止發射資料了,第三次可以看到觸發同樣在觸發onComplete後就停止發射資料了。

defer/just
  defer操作符只有當有Subscriber來訂閱的時候才會建立一個新的Observable物件,也就是說每次訂閱都會得到一個剛建立的最新的Observable物件,這可以確保Observable物件裡的資料是最新的,看原理圖:
  RxJava操作符之Creating Observables

  just操作符將某個物件轉化為Observable物件,這些物件可以是一個數字、一個字串、陣列、Iterate,並且將其一次性發射出去,是一種非常快捷的建立Observable物件的方法。
RxJava操作符之Creating Observables
  下面通過程式碼來認識一下他們之間的區別

Observable<Integer>justObservable=justOperator();
        Observable<Integer>deferObservable=deferOperator();
        Button btn_defer = (Button) findViewById(R.id.btn_defer_oper);
        btn_defer.setOnClickListener(v->deferObservable
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
//                        Log.e("defer", "onComplete");
                    }

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

                    @Override
                    public void onNext(Integer i) {
                        Log.e("defer", i+"");
                    }
                }));
        Button btn_just = (Button) findViewById(R.id.btn_just_oper);
        btn_just.setOnClickListener(v->justObservable
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
//                        Log.e("just", "onComplete");
                    }

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

                    @Override
                    public void onNext(Integer i) {
                        Log.e("just", i+"");
                    }
                }));
private Observable<Integer>deferOperator(){
        return Observable.defer(()->Observable.just(new Random().nextInt(100)));
    }
    private Observable<Integer> justOperator() {
        return Observable.just(new Random().nextInt(100));
    }

執行結果:

defer: 43
defer: 97
defer: 23
just: 98
just: 98
just: 98

  正如上文所說,defer只有在subscibe時才會生成Observable,以保證是最新的資料,而just無論訂閱幾次都是用的首次建立的Observable物件。

from
   from操作符用來將某個物件轉化為Observable物件,並且依次將其內容發射出去。聽起來和just很像,那麼它到底和just有什麼不一樣,這個類似於just,但是just會將這個物件整個發射出去。比如說一個含有10個數字的陣列,使用from就會發射10次,每次發射一個數字,而使用just會發射一次來將整個的陣列發射出去。

RxJava操作符之Creating Observables
  程式碼:
  

private List<String> dataList=new ArrayList<>();
 private void initData() {
        dataList.add("welcome");
        dataList.add("to");
        dataList.add("Rxjava");
    }
 private Observable<String> fromOperator() {
        return Observable.from(dataList);
    }
Button btn_from = (Button) findViewById(R.id.btn_from_oper);
        btn_from.setOnClickListener(v -> fromOperator()
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        Log.e("from", "onCompleted");
                    }

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

                    @Override
                    public void onNext(String s) {
                        Log.e("from", s);
                    }
                }));

  執行結果:
  

from: welcome
from: to
from: Rxjava
from: onCompleted

  
Empty/Never/Throw
  這三個操作符都是很簡單的,就拿Empty來說吧,建立一個Observable,不會發射任何的資料,但是會正常的執行OnComplete,也就是說建立了一個Empty的Observable。
RxJava操作符之Creating Observables
  程式碼:
  

private Observable emptyOperator(){
        return Observable.empty();
    }
     Button btn_empty = (Button) findViewById(R.id.btn_empty_oper);
        btn_empty.setOnClickListener(v -> emptyOperator()
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {
                        Log.e("empty", "onCompleted");
                    }

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

                    @Override
                    public void onNext(Object s) {
                        Log.e("empty", s+"");
                    }
                }));

  執行結果:

empty: onCompleted

  由於篇幅原因,有興趣的可以自己去看看其他兩個的實現。

Range
  Range操作符根據輸入的初始值n和數目m發射一系列大於等於n的m個值。
RxJava操作符之Creating Observables
具體的使用:

Button btn_range = (Button) findViewById(R.id.btn_range_oper);
        btn_range.setOnClickListener(v -> rangeOperator()
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {
                        Log.e("range", "onCompleted");
                    }

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

                    @Override
                    public void onNext(Object s) {
                        Log.e("range", s+"");
                    }
                }));
                 private Observable rangeOperator(){
        return Observable.range(1,10);
    }

執行結果

range: 1
range: 2
range: 3
range: 4
range: 5
range: 6
range: 7
range: 8
range: 9
range: 10
range: onCompleted

Interval
  Interval所建立的Observable物件會從0開始,每隔固定的時間發射一個數字。在Android這個物件預設是執行在computation Scheduler,所以如果需要在view中顯示結果,需要在切換回主執行緒。
  RxJava操作符之Creating Observables
  Interval的用法有很多,在Android可以輕鬆實現計時器的功能,那麼在使用時也有很多要注意的地方,除了上邊說的要注意執行緒的問題,還有就是在Activity中使用的時候,需要在合適的時機進行反註冊。否則可能會造成記憶體溢位。
  

Observable<Long> observable = interval();

        Subscriber<Long> subscriber = new Subscriber<Long>() {
            @Override
            public void onCompleted() {
                Log.e"onCompleted" );
            }

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

            @Override
            public void onNext(Long i) {
                Log.e("interval:" + i);
            }

        };
        sButton.setOnClickListener(e -> observable.subscribe(subscriber));
        unSButton.setOnClickListener(e -> subscriber.unsubscribe());

private Observable<Long> interval() {
        return Observable.interval(1, TimeUnit.SECONDS)
        .observeOn(AndroidSchedulers.mainThread());
    }

執行結果:

inerval:0
inerval:1
inerval:2
......

Repeat/Timer
  Repeat會重複發射一個Observable物件,並且可以指定其發射的次數。
  RxJava操作符之Creating Observables
   Timer會在指定時間後發射一個指定型別的資料,例如如果我們指定的是Long,那麼它會發射一個0。同interval一樣,其也是執行在computation Scheduler中的。注意切換主執行緒。
   RxJava操作符之Creating Observables
   這都是非常簡單的操作符,程式碼就不上了。試試就可以很清楚了。建立Observable的操作符常用的就這些了,下次將介紹Transforming Observables轉換類的操作符。

相關文章