RxJava RxAndroid - 觀察模式 + 異步 + 函數式

一、前言

閱讀本文前,建議詳細閱讀并掌握什么是觀察者模式

https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
RxJava是ReactiveX的一種Java的實現形式,擁有三大部分

  • 觀察者模式,即定義對象間一種一對多的依賴關系,當一個對象改變狀態時,則所有依賴它的對象都會被改變。
  • Iterator模式,即迭代流式編程模式。
  • 函數式編程模式,即提供一系列函數樣式的方法供快速開發。

首先RxAndroid基于RxJava,RxAndroid結合Android添加了很少的類,讓我們在Android更方便和簡單的使用RxJava。RxJava和RxAndroid已經來到了3.0+版本

RxJava核心思想:觀察者模式 + 異步 來處理事件

implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'

二、基本用法

        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
                emitter.onNext("one");
                emitter.onNext("two");
                //emitter.onComplete();
                emitter.onError(new Throwable("error"));
            }
        });
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                Log.d("yink","onSubscribe ...");
            }

            @Override
            public void onNext(@NonNull String s) {
                Log.d("yink","onNext = " + s);
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Log.d("yink","onError ... = " + e);
            }

            @Override
            public void onComplete() {
                Log.d("yink","onComplete ...");
            }
        };
        observable.subscribeOn(Schedulers.newThread());
        observable.observeOn(AndroidSchedulers.mainThread());
        Log.d("yink","subscribe ...");
        observable.subscribe(observer);

首先,RxJava基于觀察者模式,所以它的結構很簡單,無非觀察者模式三步驟:

  • Observable被觀察者,ObservableEmitter為被觀察者的幾個事件。(onComplete和onError唯一且互斥)
  • Observer觀察者,觀察幾個方法
  • observable.subscribe(observer)提交觀察者到被觀察者

其次,RxJava還額外實現了線程調度,即控制觀察者和被觀察者的代碼在哪個線程執行:

  • observable.subscribeOn(Schedulers.newThread());設置被觀察者開啟新線程來調度
  • observable.observeOn(AndroidSchedulers.mainThread());設置觀察者在主線程調度
    所以被觀察者中我們就可以做一些耗時操作,然后ObservableEmitter通知到觀察者,觀察者中可以刷新UI等操作。
2020-03-18 10:36:27.841 12678-12678/com.example.demo D/yink: subscribe ...
2020-03-18 10:36:27.841 12678-12678/com.example.demo D/yink: onSubscribe ...
2020-03-18 10:36:27.841 12678-12678/com.example.demo D/yink: onNext = one
2020-03-18 10:36:27.841 12678-12678/com.example.demo D/yink: onNext = two
2020-03-18 10:36:27.841 12678-12678/com.example.demo D/yink: onError ... = java.lang.Throwable: error

整體看來RxJava是為了讓我們更加優雅的異步,異步指定線程方便,過程好控制,還可多個觀察者,指定不同線程,這樣異步真的太方便了。

三、詳細介紹

現在我們知道RxJava大體框架,觀察者模式+異步。下面我們來看詳細介紹。詳細介紹分為下面幾個部分:

  • Observer 觀察者的各種擴展寫法
  • Observable 被觀察者的各種拓展寫法
  • 線程調度,指定線程操作相關

3.1、觀察者Observer

觀察者的擴展寫法就比較簡單

public final Disposable subscribe() 
void subscribe(@NonNull Observer<? super T> observer);
public final Disposable subscribe(@NonNull Consumer<? super T> onNext) 
public final Disposable subscribe(@NonNull Consumer<? super T> onNext, 
      @NonNull Consumer<? super Throwable> onError) 
public final Disposable subscribe(@NonNull Consumer<? super T> onNext, 
      @NonNull Consumer<? super Throwable> onError,
      @NonNull Action onComplete) 
public final Disposable subscribe(@NonNull Action onComplete) {
public final Completable doOnSubscribe(@NonNull Consumer<? super Disposable> onSubscribe) {
public final void blockingSubscribe(@NonNull Action onComplete) {
...
  • 可以看到我們提交觀察者時,觀察者的幾個變種
  • subscribe() 實際提交的是一個Functions.emptyConsumer()
  • onNext事件:Consumer<? super T>
  • onError事件:Consumer<? super Throwable>
  • onComplete事件:Action
  • Observer<? super T> observer:多種繼承自Observer的類也可以
    所以,我們在監聽上,就可以簡單只監聽部分事件。例如
Observable.just("one").subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Throwable {

            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Throwable {
                
            }
        });

這個例子就提交了兩個觀察者。一個觀察者只監聽onNext事件,一個觀察者只監聽onError事件。當然你也可以只提交一個觀察者。源碼如下,很好理解,我隨便點了一個subscribe的實現

public final Disposable subscribe(@NonNull Consumer<? super T> onNext, @NonNull Consumer<? super Throwable> onError,
           ...
        LambdaObserver<T> ls = new LambdaObserver<>(onNext, onError, onComplete, Functions.emptyConsumer());
        subscribe(ls);
        return ls;
    }

public LambdaObserver(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
            Action onComplete,
            Consumer<? super Disposable> onSubscribe) {
        super();
        this.onNext = onNext;
        this.onError = onError;
        this.onComplete = onComplete;
        this.onSubscribe = onSubscribe;
    }

@Override
    public void onNext(T t) {
        if (!isDisposed()) {
            try {
                onNext.accept(t);
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                get().dispose();
                onError(e);
            }
        }
    }

3.2、被觀察者Observable

Observable是被觀察者產生的地方,分下面幾個方面介紹:

  • Observable的創建
  • Observable操作符歸類
  • Observable擴展:Flowable、Maybe、Single、Completable

3.2.1、Observable的創建

事件產生理解上很簡單,就是創建被觀察者,我們以just的為例,看看它的整體思路

Observable.just("a","b").subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                Log.d("yink","onSubscribe ...");
            }

            @Override
            public void onNext(@NonNull String s) {
                Log.d("yink","onNext = " + s);
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Log.d("yink","onError ... = " + e);
            }

            @Override
            public void onComplete() {
                Log.d("yink","onComplete ...");
            }
        });

2020-03-24 09:30:13.562 31403-31403/com.example.demo D/yink: onSubscribe ...
2020-03-24 09:30:13.562 31403-31403/com.example.demo D/yink: onNext = a
2020-03-24 09:30:13.562 31403-31403/com.example.demo D/yink: onNext = b
2020-03-24 09:30:13.562 31403-31403/com.example.demo D/yink: onComplete ...

將對象或者對象集合轉換為一個會發射這些對象的Observable
just用法很簡單,直接把數組以onNext事件傳遞,傳遞完后 調用onComplete事件
我們接著來看看just方法的實現,篇幅原因,我省去了一些代碼。

 public static <T> Observable<T> just(@NonNull T item1, @NonNull T item2) {
        ...
        return fromArray(item1, item2);
    }

 public static <T> Observable<T> fromArray(@NonNull T... items) {
        ...
        return RxJavaPlugins.onAssembly(new ObservableFromArray<>(items));
    }

public final class ObservableFromArray<T> extends Observable<T> {
    final T[] array;
    public ObservableFromArray(T[] array) {
        this.array = array;
    }

    @Override
    public void subscribeActual(Observer<? super T> observer) {
        FromArrayDisposable<T> d = new FromArrayDisposable<>(observer, array);

        observer.onSubscribe(d);

        if (d.fusionMode) {
            return;
        }

        d.run();
    }

    static final class FromArrayDisposable<T> extends BasicQueueDisposable<T> {
        ....
        FromArrayDisposable(Observer<? super T> actual, T[] array) {
            this.downstream = actual;
            this.array = array;
        }
        ...
        void run() {
            T[] a = array;
            int n = a.length;

            for (int i = 0; i < n && !isDisposed(); i++) {
                T value = a[i];
                if (value == null) {
                    downstream.onError(new NullPointerException("The element at index " + i + " is null"));
                    return;
                }
                downstream.onNext(value);
            }
            if (!isDisposed()) {
                downstream.onComplete();
            }
        }
    }
}
  • 可以看到調用流程也很簡單,把數組挨個調用就可以了,最后發出onComplete事件
  • 事件的產生代碼都極其類似,最后定位實現都會定位到類似ObservableFromArray.java這樣的實現
  • 事件產生實現的代碼路徑在“/RxJava-3.x/src/main/java/io/reactivex/rxjava3/internal/operators/observable/**”,此路徑下有很多種實現,包括from系列,just,create,error,timer等等,只是RxJava源碼為我們默認添加的一些實現。
  • 創建觀察者思想都類似,就不一一詳述了,簡單介紹如下:
用法 簡單介紹
create 通過調用觀察者的方法從頭創建一個Observable
frome 封裝Iterable、Array、Callable、Action、Runnable、Future,以執行為核心,調用封裝的類型的內部事件。將其它的對象或數據結構轉換為Observable
targetType.from{sourceType}()
這幾種類型都是為了解決特定的問題而存在,3.1.3會簡單介紹
just 將對象或者對象集合轉換為一個會發射這些對象的Observable
defer 普通observable創建對象時就確定了參數,defer則是我們提交觀察者時才去創建被觀察者和參數,相當于一個懶加載,在觀察者訂閱之前不創建這個Observable,為每一個觀察者創建一個新的Observable
range rang(0,10)直接生成0-10事件,創建發射指定范圍的整數序列的Observable
interval interval(1, TimeUnit.SECONDS);周期性生成一個無限的、永遠增長的數(長整型)
timer Observable.timer(5, TimeUnit.MINUTES)延時五分鐘發送事件
empty 創建一個不發射任何數據但是正常終止的Observable,只調用一個onCompleted方法
never 創建一個什么事件都不發送的被觀察者
error 發送error事件

3.2.2、ObservableObservable操作符歸類

Rxjava提供的操作符真的蠻多的。主要分為下面幾個大類

  • 直接創建一個Observable(創建操作)
  • 組合多個Observable(組合操作)
  • 對Observable發射的數據執行變換操作(變換操作)
  • 從Observable發射的數據中取特定的值(過濾操作)
  • 轉發Observable的部分值(條件/布爾/過濾操作)
  • 對Observable發射的數據序列求值(算術/聚合操作)

這段歸類描述引用自知乎的一個回答,Rxjava、rxandroid中的操作,這里我將其制成表格,供大家查閱使用,上面有創建操作符表格,所以下面是省略這部分。

變換操作

用法 簡單介紹
Buffer 緩存,可以簡單的理解為緩存,它定期從Observable收集數據到一個集合,然后把這些數據集合打包發射,而不是一次發射一個
FlatMap 扁平映射,將Observable發射的數據變換為Observables集合,然后將這些Observable發射的數據平坦化的放進一個單獨的Observable,可以認為是一個將嵌套的數據結構展開的過程。
GroupBy 分組,將原來的Observable分拆為Observable集合,將原始Observable發射的數據按Key分組,每一個Observable發射一組不同的數據
Map 映射,通過對序列的每一項都應用一個函數變換Observable發射的數據,實質是對序列中的每一項執行一個函數,函數的參數就是這個數據項
Scan 掃描,對Observable發射的每一項數據應用一個函數,然后按順序依次發射這些值
Window 窗口,定期將來自Observable的數據分拆成一些Observable窗口,然后發射這些窗口,而不是每次發射一項。類似于Buffer,但Buffer發射的是數據,Window發射的是Observable,每一個Observable發射原始Observable的數據的一個子集
lift 把事件處理一次后再發送到Observer

過濾操作

用法 簡單介紹
Debounce 只有在空閑了一段時間后才發射數據,通俗的說,就是如果一段時間沒有操作,就執行一次操作
Distinct 去重,過濾掉重復數據項
ElementAt 取值,取特定位置的數據項
Filter 過濾,過濾掉沒有通過謂詞測試的數據項,只發射通過測試的
First 首項,只發射滿足條件的第一條數據
IgnoreElements 忽略所有的數據,只保留終止通知(onError或onCompleted)
Last 末項,只發射最后一條數據
Sample 取樣,定期發射最新的數據,等于是數據抽樣,有的實現里叫ThrottleFirst
Skip 跳過前面的若干項數據
SkipLast 跳過后面的若干項數據
Take 只保留前面的若干項數據
TakeLast 只保留后面的若干項數據

組合操作

用法 簡單介紹
And/Then/When 通過模式(And條件)和計劃(Then次序)組合兩個或多個Observable發射的數據集
CombineLatest 當兩個Observables中的任何一個發射了一個數據時,通過一個指定的函數組合每個Observable發射的最新數據(一共兩個數據),然后發射這個函數的結果
Join 無論何時,如果一個Observable發射了一個數據項,只要在另一個Observable發射的數據項定義的時間窗口內,就將兩個Observable發射的數據合并發射
Merge 將兩個Observable發射的數據組合并成一個
StartWith 在發射原來的Observable的數據序列之前,先發射一個指定的數據序列或數據項
Switch 將一個發射Observable序列的Observable轉換為這樣一個Observable:它逐個發射那些Observable最近發射的數據
Zip 打包,使用一個指定的函數將多個Observable發射的數據組合在一起,然后將這個函數的結果作為單項數據發射

錯誤處理
這些操作符用于從錯誤通知中恢復

用法 簡單介紹
Catch 捕獲,繼續序列操作,將錯誤替換為正常的數據,從onError通知中恢復
Retry 重試,如果Observable發射了一個錯誤通知,重新訂閱它,期待它正常終止

輔助操作

用法 簡單介紹
Delay 延遲一段時間發射結果數據
Do 注冊一個動作占用一些Observable的生命周期事件,相當于Mock某個操作
Materialize/Dematerialize 將發射的數據和通知都當做數據發射,或者反過來
ObserveOn 指定觀察者觀察Observable的調度程序(工作線程)
Serialize 強制Observable按次序發射數據并且功能是有效的
Subscribe 收到Observable發射的數據和通知后執行的操作
SubscribeOn 指定Observable應該在哪個調度程序上執行
TimeInterval 將一個Observable轉換為發射兩個數據之間所耗費時間的Observable
Timeout 添加超時機制,如果過了指定的一段時間沒有發射數據,就發射一個錯誤通知
Timestamp 給Observable發射的每個數據項添加一個時間戳
Using 創建一個只在Observable的生命周期內存在的一次性資源

條件和布爾操作

用法 簡單介紹
All 判斷Observable發射的所有的數據項是否都滿足某個條件
Amb 給定多個Observable,只讓第一個發射數據的Observable發射全部數據
Contains 判斷Observable是否會發射一個指定的數據項
DefaultIfEmpty 發射來自原始Observable的數據,如果原始Observable沒有發射數據,就發射一個默認數據
SequenceEqual 判斷兩個Observable是否按相同的數據序列
SkipUntil 丟棄原始Observable發射的數據,直到第二個Observable發射了一個數據,然后發射原始Observable的剩余數據
SkipWhile 丟棄原始Observable發射的數據,直到一個特定的條件為假,然后發射原始Observable剩余的數據
TakeUntil 發射來自原始Observable的數據,直到第二個Observable發射了一個數據或一個通知
TakeWhile 發射原始Observable的數據,直到一個特定的條件為真,然后跳過剩余的數據

算術和聚合操作

用法 簡單介紹
Average 計算Observable發射的數據序列的平均值,然后發射這個結果
Concat 不交錯的連接多個Observable的數據
Count 計算Observable發射的數據個數,然后發射這個結果
Max 計算并發射數據序列的最大值
Min 計算并發射數據序列的最小值
Reduce 按順序對數據序列的每一個應用某個函數,然后返回這個值
Sum 計算并發射數據序列的和

連接操作

用法 簡單介紹
Connect 指示一個可連接的Observable開始發射數據給訂閱者
Publish 將一個普通的Observable轉換為可連接的
RefCount 使一個可連接的Observable表現得像一個普通的Observable
Replay 確保所有的觀察者收到同樣的數據序列,即使他們在Observable開始發射數據之后才訂閱

轉換操作

用法 簡單介紹
To 將Observable轉換為其它的對象或數據結構
Blocking 阻塞Observable的操作符

這幾個表格的目的是方便大家查閱,我們不需要一口氣學習所有操作符,知其思想即可。這些操作符目的加工Observable
由于篇幅原因這里只舉一個map例子,上面所有操作符都很容易上手使用,就不過多闡述。

Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
            emitter.onNext(1);
            emitter.onNext(2);
            emitter.onNext(3);
        }
    }).map(new Function<Integer, String>() {
        @Override
        public String apply(Integer integer) throws Exception {
            return "map add " + integer;
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d("yink", s);
        }
    });

2020-03-24 14:59:30.518 8467-8467/com.example.demo D/yink: map add 1
2020-03-24 14:59:30.518 8467-8467/com.example.demo D/yink: map add 2
2020-03-24 14:59:30.518 8467-8467/com.example.demo D/yink: map add 3

自定義操作符
自定義操作符有兩個方向:

  • 對Observable被觀察者中的數據動刀,讓數據轉換一次,最后再發送到觀察者。
  • 對Observable被觀察者直接動刀,轉換一次被觀察者
    1、實現ObservableOperator接口,轉換數據
@FunctionalInterface
public interface ObservableOperator<@NonNull Downstream, @NonNull Upstream> {
    @NonNull
    Observer<? super Upstream> apply(@NonNull Observer<? super Downstream> observer) throws Throwable;
}

Observable.just("1","2")
                  .lift(new YourClass<String>())

2、實現ObservableOperator

public interface ObservableTransformer<Upstream, Downstream> {
    @NonNull
    ObservableSource<Downstream> apply(@NonNull Observable<Upstream> upstream);
}

Observable.just("1","2")
                  .compose(new YourTransformer())
                  .subscribe...

3.2.3、Observable擴展

Flowable、Maybe、Single、Completable

Flowable
Flowable為了解決背壓的問題而存在。直接上例子:

Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> e) throws Exception {
                for(int j = 0; j <= 100; j++){
                    e.onNext(j);
                    Log.i("yink"," send id = " + j);
                    try{
                        Thread.sleep(50);
                    }catch (Exception ex){
                    }
                }
            }
        }, BackpressureStrategy.MISSING)
                .subscribeOn(Schedulers.newThread())
                .observeOn(Schedulers.newThread())
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(Long.MAX_VALUE); //觀察者設置接收事件的數量,如果不設置接收不到事件
                    }
                    @Override
                    public void onNext(Integer integer) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Log.e("yink","onNext = " + integer);
                    }
                    @Override
                    public void onError(Throwable t) {
                        Log.e("yink","onError = " + t.toString());
                    }
                    @Override
                    public void onComplete() {
                        Log.e("yink","onComplete");
                    }
                });
  • 背壓:被觀察者發送事件的速度大于觀察者接收的速度時,觀察者內部是創建一個無限大的緩存來暫存沒有處理的事件。如果事件太多會導致OOM。
  • Flowable提供了幾種方式來避免無限放大的緩存
  • Flowable 在使用上并無太大差別,多了一個BackpressureStrategy參數,必須指定接收事件數量
  • Flowable 緩存池默認大小是128
  • BackpressureStrategy參數就是Flowable設置在背壓發生時處理的方式,參數類型如下:
public enum BackpressureStrategy {
    MISSING,
    ERROR,
    BUFFER,
    DROP,
    LATEST
}
類型 簡單介紹
MISSING 不采取任何背壓策略(既不丟棄,也不緩存),超出隊列大小會拋出onError事件,不影響事件發送,拋出MissingBackpressureException: Queue is full?!
ERROR 萬一下游跟不上,拋出MissingBackpressureException: create: could not emit value due to lack of requests
BUFFER 緩存所有
DROP 下游處理跟不上,刪除最新
LATEST 下游處理跟不上,只保留最新

Single
Single,用法如其名,它只有onSuccess和onError事件,只發送一次事件。例子如下比較簡單:

      Single.create(new SingleOnSubscribe<String>() {

            @Override
            public void subscribe(@NonNull SingleEmitter<String> e) throws Exception {

                e.onSuccess("1");
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {
                Log.d("yink","s = " + s.toString());
            }
        });

public interface SingleEmitter<@NonNull T> {
    void onSuccess(@NonNull T t);
    void onError(@NonNull Throwable t);
    void setDisposable(@Nullable Disposable d);
    void setCancellable(@Nullable Cancellable c);
    boolean isDisposed();
    boolean tryOnError(@NonNull Throwable t);
}

Completable
Completable不發送任何數據,發送onComplete和onError,用法也比較簡單,下面例子就是,線程執行完了,接著可以做別的。因為線程執行時也不用發出什么事件,或者發送值。
Completable還支持toXXX,轉換成Flowable/Single/Maybe/Observable

Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(@NonNull CompletableEmitter emitter) throws Exception {
                try{
                        Thread.sleep(50);
                    }catch (Exception ex){
                    }
            }
        }).andThen(Observable.range(1, 10))
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(@NonNull Integer integer) throws Exception {
                Log.d("yink","integer = " + integer);
            }
        });

public interface CompletableEmitter {
    void onComplete();
    void onError(@NonNull Throwable t);
    void setDisposable(@Nullable Disposable d);
    void setCancellable(@Nullable Cancellable c);
    boolean isDisposed();
}

Maybe
Maybe可以理解為Single和Completable的結合。看事件就理解了,Maybe只能傳一次值onSuccess,然后支持onComplete和onError事件。

      Maybe.create(new MaybeOnSubscribe<String>() {

            @Override
            public void subscribe(@NonNull MaybeEmitter<String> e) throws Exception {
                e.onSuccess("testA");
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {
                Log.d("yink", " s = " + s);
            }
        });

public interface MaybeEmitter<@NonNull T> {
    void onSuccess(@NonNull T t);
    void onError(@NonNull Throwable t);
    void onComplete();
    void setDisposable(@Nullable Disposable d);
    void setCancellable(@Nullable Cancellable c);
    boolean isDisposed();
    boolean tryOnError(@NonNull Throwable t);
}

所以Rxjava提供五種被觀察者寫法:Observable、Flowable、Maybe、Single、Completable。可以方便我們再合適的地方用合適的類,寫出更優美的代碼。

3.3、線程調度

此小結為RxJava最騷的地方,正是因為RxJava在觀察者模式上增加了線程調度,所以讓異步變得如此優美。

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
                Log.e("yink", "Observable call: " + Thread.currentThread().getName());
                emitter.onNext("one");
                emitter.onNext("two");
            }
        })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Throwable {
                Log.e("yink", "Observer call: " + Thread.currentThread().getName());
                Log.d("yink","s = " + s);
            }
        });

2020-03-25 09:31:38.388 29612-29724/com.example.demo E/yink: Observable call: RxNewThreadScheduler-1
2020-03-25 09:31:38.417 29612-29612/com.example.demo E/yink: Observer call: main
2020-03-25 09:31:38.417 29612-29612/com.example.demo D/yink: s = one
2020-03-25 09:31:38.417 29612-29612/com.example.demo E/yink: Observer call: main
2020-03-25 09:31:38.417 29612-29612/com.example.demo D/yink: s = two
方法 簡單介紹
Schedulers.io() 用于IO密集型的操作,線程緩存(有空閑則復用,否則無限增加)
Schedulers.newThread() 每次創建一個新線程,不具有緩存
Schedulers.single() 單線程,先進先出
Schedulers.computation() cpu密集型計算任務,具有固定的線程池,大小為CPU核數,不可以用于IO操作,因為IO操作的等待時間會浪費cpu
Schedulers.trampoline() 立即執行當前添加任務A,若有一個B任務正在執行,則暫停B,執行完A后再接著執行B
Schedulers.from(Executor) 提供帶入線程池的方式
AndroidSchedulers.mainThread() RxAndroid擴展,Android中UI線程中執行
AndroidSchedulers.from(Looper) RxAndroid擴展,Looper當前循環線程執行

RxJava/RxAndroid默認給我們線程調度方式基本涵蓋了我們絕大部分會使用的情況。

四、RxAndroid

RxAndroid中的代碼很少,它擴展的意義在于方便我們結合Android特性,在UI線程中調度。或者結合Handler調度。舉兩個例子

public class ReactiveFragment extends Fragment {//在UI線程中的例子
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Observable.just("one", "two", "three", "four", "five")
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(/* an Observer */);
    }

new Thread(new Runnable() {//在其他線程中的例子
    @Override
    public void run() {
        final Handler handler = new Handler(); //綁定到這個線程的Handler
        Observable.just("one", "two", "three", "four", "five")
                .subscribeOn(Schedulers.newThread())
                .observeOn(HandlerScheduler.from(handler))
                .subscribe(/* an Observer */)
    }
}, "custom-thread-1").start();

五、寫在最后

到此RxJava和RxAndroid介紹的差不多了。本文主要目的是全方位的介紹一下RxJava,主要拆分成:被觀察者 + 觀察者 + 異步,分部分來講解。來達到對RxJava有一個整體上,不光是用法,還有思想上的理解。希望本文對你有所幫助。有啥對或者不對的地方,歡迎交流,指正。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容