RxJava學習筆記

RxJava和Retrofit的依賴

? ??//rxjava依賴

? ??implementation'io.reactivex.rxjava2:rxjava:2.0.1'

? ??implementation'io.reactivex.rxjava2:rxandroid:2.0.1'

? ??//retrofit

? ??compile'com.squareup.retrofit2:retrofit:2.1.0'

? ??//Gson converter

? ??compile'com.squareup.retrofit2:converter-gson:2.1.0'

? ??/RxJava2 Adapter

? ??compile'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

? ??//okhttp

? ??compile'com.squareup.okhttp3:okhttp:3.4.1'

? ??compile'com.squareup.okhttp3:logging-interceptor:3.4.1'


1. RxJava鏈式寫法,線程切換

Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

Log.d(TAG, "emitter 1");

emitter.onNext("1");

Log.d(TAG, "emitter 2");

emitter.onNext("2");

Log.d(TAG, "emitter onComplete");

emitter.onComplete();

Log.d(TAG, "emitter 3");

emitter.onNext("3");

}

}).subscribeOn(Schedulers.newThread())?

.subscribeOn(Schedulers.io())??

.observeOn(AndroidSchedulers.mainThread())?

.observeOn(Schedulers.newThread())

.subscribe(new Observer() {

private int i;

@Override

public void onSubscribe(Disposable disposable) {

TestRxJavaActivity.this.disposable = disposable;

Log.d(TAG, "onSubscribe");

}

@Override

public void onNext(String value) {

Log.d(TAG, "onNext value:" + value);

i++;

if (i == 2) {

Log.d(TAG, "dispose");

disposable.dispose();

Log.d(TAG, "isDisposed:" + disposable.isDisposed());

}

}

@Override

public void onError(Throwable e) {

Log.d(TAG, "onError");

}

@Override

public void onComplete() {

Log.d(TAG, "onComplete");

}});

ObservableEmitter:發射器,用來發出事件,可以發出三種類型的事件,通過調用emitter的onNext(T value)onComplete()onError(Throwable error)就可以分別發出next事件、complete事件和error事件

? ? 不可以隨意亂七八糟發射事件,需要滿足一定的規則:

? ? ? ?① 上游可以發送無限個onNext, 下游也可以接收無限個onNext.

????????②當上游發送了一個onComplete后, 上游onComplete之后的事件將會繼續發送, 而下游收到onComplete事件之后將不再繼續接收事件.

????????③當上游發送了一個onError后, 上游onError之后的事件將繼續發送, 而下游收到onError事件之后將不再繼續接收事件.

? ? ? ? ④上游可以不發送onComplete或onError.

? ? ? ? ⑤最為關鍵的是onComplete和onError必須唯一并且互斥, 即不能發多個onComplete, 也不能發多個onError, 也不能先發一個onComplete, 然后再發一個onError, 反之亦然

注: 關于onComplete和onError唯一并且互斥這一點, 是需要自行在代碼中進行控制, 如果你的代碼邏輯中違背了這個規則, **并不一定會導致程序崩潰. ** 比如發送多個onComplete是可以正常運行的, 依然是收到第一個onComplete就不再接收了, 但若是發送多個onError, 則收到第二個onError事件會導致程序會崩潰.??


2. RxJava中內置的線程

????Schedulers.io() 代表io操作的線程, 通常用于網絡,讀寫文件等io密集型的操作

? ??Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作

????Schedulers.newThread() 代表一個常規的新線程

? ??AndroidSchedulers.mainThread() 代表Android的主線程

這些內置的Scheduler已經足夠滿足我們開發的需求, 因此我們應該使用內置的這些選項, 在RxJava內部使用的是線程池來維護這些線程, 所以效率也比較高.

線程切換:

? ??.subscribeOn(Schedulers.newThread()) //指定的是上游發送事件的線程

????.observeOn(AndroidSchedulers.mainThread()) //指定的是下游接收事件的線程.

多次指定上游的線程只有第一次指定的有效, 也就是說多次調用subscribeOn()?只有第一次的有效, 其余的會被忽略.

多次指定下游的線程是可以的, 也就是說每調用一次observeOn()?, 下游的線程就會切換一次.


3. 在Activity退出時要切斷水管(訂閱),調用Disposabledispose()方法切斷連接,如果有多個Disposable,使用RxJava中內置的容器CompositeDisposable, 每得到一個Disposable就調用?CompositeDisposable.add(),將它添加到容器中,在Activity退出的時候, 調用CompositeDisposable.clear()?即可切斷所有的水管(訂閱)


4. 最簡單的map轉換操作符:

? ? 通過map, 可以將上游發來的事件轉換為任意的類型, 可以是一個Object, 也可以是一個集合.

? ? 示例代碼:

? ??????.map(new Function<Integer, String>() {

? ? ? ? ? ? //將Integer轉成String類型

????????????@Override

????????????public??String apply(Integer integer) throws Exception{

????????????return"This is result "+ integer;?

?????????} })


5. flatMap操作符:

? ??上游每發送一個事件, flatMap都將創建一個新的水管, 然后發送轉換之后的新的事件, 下游接收到的就是這些新的水管發送的數據.這里需要注意的是, flatMap并不保證事件的順序,也就是圖中所看到的, 并不是事件1就在事件2的前面. 如果需要保證順序則需要使用concatMap,用法一模一樣

????示例代碼:

? ? ? ? .concatMap(newFunction<String, ObservableSource<Integer>>() {

????????????@Override

????????????public ObservableSource??apply(Integer integer)throws Exception{

????????????????final List list =new ArrayList<>();

????????????????for(int i =0; i <3; i++) {?

?????????????????????list.add("I am value "+ integer);?

?????????????????}

? ? ? ? ?????????return Observable.fromIterable(list);

? ? ? } })

????實踐示例:可以實現嵌套請求,如注冊完成去登錄就可以使用concatMap或者flatMap了


6. zip操作符通過一個函數將多個Observable發送的事件結合到一起,然后發送這些組合到一起的事件. 它按照嚴格的順序應用這個函數。它只發射與發射數據項最少的那個Observable一樣多的數據。并且一個事件只能被使用一次,?組合的順序是嚴格按照事件發送的順序來進行的.并且發送的事件都是在同一線程,需要切換線程,發送事件才可以在不同線程同步進行發送.

? ? 示例代碼:

? ??????Observable.zip(observable1, observable2,new BiFunction<Integer,String,String>(){

????????????@Override

?????????????public String apply(Integer integer, String s)throws Exception{

????????????????????return? integer + s;

?????????} })

? ? 實踐示例:比如一個界面需要展示用戶的一些信息, 而這些信息分別要從兩個服務器接口中獲取, 而只有當兩個都獲取到了之后才能進行展示, 這個時候就可以用Zip了

7. filter:過濾操作符,過濾上游事件

? ? ? ? 示例代碼:

? ??????????.filter(new Predicate() {

????????????????@Override

? ????????????? public boolean test(Integer integer)throws Exception {

????????????????????return integer%10==0;

????????????????}

????????????})

8. sample:取樣操作符,每隔指定的時間就從上游中取出一個事件發送給下游

? ? 示例代碼:.sample(2, TimeUnit.SECONDS)//沒個兩秒sample取樣一次上游事件

9.Flowable的使用

? ? 上游是Flowable,下游是Subscriber,鏈接不變,和Observable用法一樣,只是多了一個?背壓策略參數:BackpressureStrategy.ERROR;

Flowable在設計的時候采用了一種新的思路也就是響應式拉取的方式來更好的解決上下游流速不均衡的問題;

FLowable相比Observable, 在性能方面有些不足, 畢竟FLowable內部為了實現響應式拉取做了更多的操作, 性能有所丟失也是在所難免;

Flowable默認最多可以存放128個事件;

背壓策略:

? ?? BackpressureStrategy.ERROR:當下游沒有處理事件能力是拋出 MissingBackpressureException異常

? ?? BackpressureStrategy.BUFFER:上游水缸沒有大小限制;

? ? ?BackpressureStrategy.DROP: 直接把存不下的事件丟棄;

? ?? BackpressureStrategy.LATEST:只保留最新的事件;

? ? 注:Latest和Drop的區別在于Latest總是能獲取到最后最新的事件;

Flowable<Integer> upstream = Flowable.create(new FlowableOnSubscribe<Integer>(){

????????@Override?

????????public void subscribe(FlowableEmitter<Integer> emitter)throws Exception{? ? ? ? ? ? ? ? ? ?????????????Log.d(TAG,"emit 1");?

?????????????emitter.onNext(1);

?????????????Log.d(TAG,"emit 2");

?????????????emitter.onNext(2);?

?????????????Log.d(TAG,"emit 3");

?????????????emitter.onNext(3);

?????????????Log.d(TAG,"emit complete");

?????????????emitter.onComplete();

?????????}??}, BackpressureStrategy.ERROR);//增加了一個參數,背壓策略

? ??????Subscriber<Integer> downstream =new Subscriber<Integer>() {

? ? ? ? ? ? ? ?@Override

????????????????publicvoid onSubscribe(Subscription s){?

?????????????????????Log.d(TAG,"onSubscribe");?

?????????????????????s.request(Long.MAX_VALUE);//注意這句代碼

????????????????}

????????????@Override?

????????????public void onNext(Integer integer){

?????????????????Log.d(TAG,"onNext: "+ integer); }

????????????@Override

????????????public void onError(Throwable t){?

?????????????????Log.w(TAG,"onError: ", t); }

????????????@Override

? ? ? ? ? ? ?public void onComplete(){?

?????????????????Log.d(TAG,"onComplete");

? ? ? ? ? } };?

?????????upstream.subscribe(downstream);

10.下游Subscriber的onSubcribe方法中傳遞的是一個Subscription,它也是上下游的一個開關,調用Subscription.cancel()也可以切斷水管,同時也增加一個Subscription.requset(3)方法,該方法代表下游處理事件的能力,參數是幾就是代表能處理幾個事件

11.同一線程中在上游使用FlowableEmitter.requested()獲取下游處理事件能力的多少;

? ??當上下游工作在不同的線程里時,每一個線程里都有一個requested方法,而我們調用request(1000)時,實際上改變的是下游線程中的requested,而上游中的requested的值是由RxJava內部調用request(n)去設置的,這個調用會在合適的時候自動觸發。

注:不同線程中下游每消費96個事件便會自動觸發內部的request()去設置上游的requested的值, 發送事件前先判斷當前的requested的值是否大于0,若等于0則說明下游處理不過來了,則需要等待

12.只有onNext()事件才會消耗事件,complete和error事件不會消耗requested;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 怎么如此平靜, 感覺像是走錯了片場.為什么呢, 因為上下游工作在同一個線程呀騷年們! 這個時候上游每次調用emit...
    Young1657閱讀 1,510評論 2 1
  • 轉載自:https://xiaobailong24.me/2017/03/18/Android-RxJava2.x...
    Young1657閱讀 2,036評論 1 9
  • 1.rxjava介紹 RxJava is a Java VM implementation of Reactive...
    mercuryli閱讀 233評論 0 0
  • 參閱給 Android 開發者的 RxJava 詳解什么是函數式編程RxJava 2.0 全新來襲基于RxJava...
    小編閱讀 1,998評論 0 5
  • 今天上午看春晚重播,忽然被好多節目感染了,原來昨天沒有專注地去看。 下午百無聊賴,于是去東山的雨花臺爬山。來到山里...
    顧鳴芬閱讀 143評論 0 0