RxJava操作符之建立操作符(三)

LeiHolmes發表於2017-10-31

前言

  通過前兩篇文章對於RxJava概念,原理及使用的學習,想必各位碼友已經基本掌握RxJava的邏輯與功能了,那麼從這篇文章開始我們來研究RxJava的各類操作符。
  
  什麼是操作符?通過之前的學習,我們發現Observable負責傳送事件,Observer負責接收事件,而這個過程中想要對事件資料做出修改就需要交給操作符來負責啦。主流RxJava中操作符主要分為三類:轉換操作符,過濾操作符,組合操作符。而我個人將用來建立Observable的操作符歸為了一個新型別。本篇我們就來看看常用的建立操作符都有哪些以及如何使用。

建立操作符

Create

  上一篇文章的例子中我們已經實踐了create操作符如何使用了,這裡我們介紹一種便捷的建立Observer的方式。

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        for (int i = 0; i < 5; i++) {
            subscriber.onNext("xulei" + i);
        }
        subscriber.onCompleted();
    }
}).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "create:" + s);
    }
});複製程式碼

  subscribe()的入參使用Action1代替原來的Observer,只需重寫一個call()方法,等同於原Observer中onNext()方法。如果需要onComplete與onError狀態,還可以如下:

.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "create:" + s);
    }
}, new Action1<Throwable>() {
    @Override
    public void call(Throwable throwable) {
        Log.e("rx_test", "onError:" + throwable.getMessage());
    }
}, new Action0() {
    @Override
    public void call() {
        Log.e("rx_test", "onCompleted");
    }
});複製程式碼

  使用new ActionX代替new Observer,程式碼是不是看起來更加靈活與簡潔呢。

Just

  just操作符可將某個或某些物件轉化為Observable物件,並將其發射出去。引數可為一個或多個數字,字串。也可為集合,陣列,Iterate物件等。

Observable.just(1, 2, 3, 4, 5, 6).subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer integer) {
        Log.e("rx_test", "just:數字:" + integer);
        //數字或者字串都是單個發射多次
    }
});

List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.just(stringList).subscribe(new Action1<List<String>>() {
    @Override
    public void call(List<String> strings) {
        Log.e("rx_test", "just:集合:" + strings.toString());
        //集合或陣列是直接發射集合整體,不會拆分
    }
});複製程式碼

  輸出結果:

just:數字:1
just:數字:2
just:數字:3
just:數字:4
just:數字:5
just:數字:6
just:集合:[Hello, Ha, RxJava]複製程式碼

From

  from操作符可將某個物件轉化為Observable物件,並且將其發射出去。不同於just,他接收集合或陣列,並可將集合陣列遍歷之後拆分傳送。

List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.from(stringList).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "from:" + s);
    }
});複製程式碼

  輸出結果:

from:Hello
from:Ha
from:RxJava複製程式碼

Range

  range(int start, int count)操作符,根據初始值start,與數量count,發射count次以start為基數依次增加的值。

Observable.range(4, 5).subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer integer) {
        Log.e("rx_test", "range:" + integer);
    }
});複製程式碼

  輸出結果:

range:4
range:5
range:6
range:7
range:8複製程式碼

Defer

  defer操作符功能類似於just操作符,不同之處在於defer只有在呼叫subscribe()方法進行訂閱時才建立Observable,而just操作符在初始化Observable就已經建立了,且只建立一個Observable例項。這裡我們通過與just對比進行實踐。

Action1<String> action1 = new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", s);
    }
};

//defer
Observable<String> deferObservable = Observable.defer(new Func0<Observable<String>>() {
    @Override
    public Observable<String> call() {
        Object o = new Object();
        return Observable.just("defer:hashCode:" + o.hashCode());
    }
});
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);

//just
Observable<String> justObservable = Observable.just("just:hashCode:" + new Object().hashCode());
justObservable.subscribe(action1);
justObservable.subscribe(action1);
justObservable.subscribe(action1);複製程式碼

  輸出結果:

defer:hashCode:112449879
defer:hashCode:118897732
defer:hashCode:191664429
just:hashCode:121878114
just:hashCode:121878114
just:hashCode:121878114複製程式碼

  由輸出結果我們可以看出defer每次輸出的Observable哈西值是不同的,說明其每subscribe訂閱一次都會建立一個新的Observable,從而可保證Observable中的資料都是最新的。而just只有初始化的時候建立一次Observable。

Interval

  interval建立操作符,建立一個Observabel並每隔一段時間週期發射一個由0開始增加的數字。
  注意:此Observabel是執行在新的執行緒,所以更新UI需要在主執行緒中訂閱

//每隔100ms發射一個數字,從0自增
Observable.interval(100, TimeUnit.MILLISECONDS) //單位為毫秒
        .observeOn(AndroidSchedulers.mainThread())
        .take(5) //取前5次事件發射,take為過濾操作符,後期會詳細講
        .subscribe(new Action1<Long>() {
            @Override
            public void call(Long aLong) {
                Log.e("rx_test", "interval:" + aLong);
            }
        });複製程式碼

  輸出結果:

100ms後...
interval:0
100ms後...
interval:1
100ms後...
interval:2
100ms後...
interval:3
100ms後...
interval:4複製程式碼

Timer

  timer操作符,建立一個Observable並隔一段時間後發射一個特殊的值,僅發射一次。
  注意:此Observabel是執行在新的執行緒,所以更新UI需要在主執行緒中訂閱

//隔1s後發射一個數字
Observable.timer(1, TimeUnit.SECONDS) //單位為秒
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Long>() {
            @Override
            public void call(Long aLong) {
                Log.e("rx_test", "timer:" + aLong);
            }
        });複製程式碼

  輸出結果:

1秒後...
timer:0複製程式碼

Delay

  delay操作符,可用於延遲一定時長再傳送事件。

//延遲2秒後發射事件
Observable.just(1, 2, 3)
        .delay(2, TimeUnit.SECONDS)
        .subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.e("rx_test", "delay:" + integer);
            }
        });複製程式碼

  輸出結果:

2秒後...
delay:1
delay:2
delay:3複製程式碼

Repeat

  repeat(long count)操作符,將Observable重複發射count次。

//重複發射5次“Sherlock”
Observable.just("Sherlock").repeat(5)
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("rx_test", "repeat:" + s);
            }
     });複製程式碼

  輸出結果:

repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock複製程式碼

  以上就是常用的一些建立操作符,類似但不常用的還有empty、never、error等等就不一一介紹了,有興趣的碼友可以自行百度。

執行緒排程Scheduler

  RxJava就是用來處理非同步任務的,所以就牽扯到生產事件所線上程,處理事件所線上程的問題,下面來看一下RxJava提供的執行緒排程Scheduler都有哪些。


  有了Scheduler,RxJava當然也提供了方法來使用它們。
  .subscribeOn()指定被觀察者Observable的執行執行緒。
  .observeOn()指定觀察者Observer的執行執行緒。
  
  如第一篇文章中的例子:

//獲取要查詢的小區集合
Observable.from(getCommunitiesFromServer())
        .flatMap(new Func1<Community, Observable<House>>() {
            @Override
            public Observable<House> call(Community community) {
                return Observable.from(community.getHouses());
            }
        })
        .filter(new Func1<House, Boolean>() {
            @Override
            public Boolean call(House house) {
                return house.getPrice() < 200;
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<House>() {
            @Override
            public void call(House house) {
                //顯示查詢出來的房源資訊
                ShowSearchedHousesMessage();
            }
        });複製程式碼

  其中.subscribeOn(Schedulers.io())指定了Observable在io執行緒執行,通常用來執行從伺服器獲取資料,資料庫載入等耗時操作。.observeOn(AndroidSchedulers.mainThread())指定了Observer在Android環境下的UI執行緒執行,通常用來獲取到資料後進行UI重新整理的操作。可根據實際需求選擇不同執行緒型別。

總結

  到此,本篇關於RxJava的建立類操作符以及執行緒排程就講解完畢了,下一篇我們將一起研究RxJava的四類操作符中的轉換操作符都有哪些以及如何使用。
  技術渣一枚,有寫的不對的地方歡迎大神們留言指正,有什麼疑惑或者建議也可以在我Github上RxJavaDemo專案Issues中提出,我會及時回覆。
  附上RxJavaDemo的地址:
  RxJavaDemo

相關文章