RxJava - Subject使用及示例

RxJava的四種Subjects:PublishSubject、ReplaySubject、BehaviorSubject、AsyncSubject的理解

Subject:它既是Observable,又是observer。也就是既可以發送事件,也可以接收事件。

Subject將觀察者和被觀察者結合爲一體,是觀察者和被觀察者的代理。

下面是四個子類PublishSubject、ReplaySubject、BehaviorSubject、AsyncSubject的區別:

PublishSubject<Integer> source = PublishSubject.create();  //PublicSubject:接收到訂閱之後的所有數據。
// It will get 1, 2, 3, 4 and onComplete
source.subscribe(getFirstObserver()); 
source.onNext(1);
source.onNext(2);
source.onNext(3);
// It will get 4 and onComplete for second observer also.
source.subscribe(getSecondObserver());
source.onNext(4);
source.onComplete();
ReplaySubject<Integer> source = ReplaySubject.create();  //ReplaySubject:接收到所有的數據,包括訂閱之前的所有數據和訂閱之後的所有數據。
// It will get 1, 2, 3, 4
source.subscribe(getFirstObserver());
source.onNext(1);
source.onNext(2);
source.onNext(3);
source.onNext(4);
source.onComplete();
// It will also get 1, 2, 3, 4 as we have used replay Subject
source.subscribe(getSecondObserver());
BehaviorSubject<Integer> source = BehaviorSubject.create();  //BehaviorSubject:接收到訂閱前的最後一條數據和訂閱後的所有數據。
// It will get 1, 2, 3, 4 and onComplete
source.subscribe(getFirstObserver());
source.onNext(1);
source.onNext(2);
source.onNext(3);
// It will get 3(last emitted)and 4(subsequent item) and onComplete
source.subscribe(getSecondObserver());
source.onNext(4);
source.onComplete();
AsyncSubject<Integer> source = AsyncSubject.create();  //AsyncSubject:不管在什麼位置訂閱,都只接接收到最後一條數據
// It will get only 4 and onComplete
source.subscribe(getFirstObserver());
source.onNext(1);
source.onNext(2);
source.onNext(3);
// It will also get only get 4 and onComplete
source.subscribe(getSecondObserver());
source.onNext(4);
source.onComplete();

Subject使用及示例

本文介紹RxJava中Subject的使用。小白同學們看清楚並記好了,這裏講的是Subject,不是Subscribe,不是Subscription,不是subscribeOn,不是OnSubscribe,不是Schedulers,更不是Single,而是Subject

這麼多S開頭的的單詞有沒有把你弄糊塗啊,英語好的同學可以略過這段。這裏把RxJava中容易和Subject弄混的概念都拿出來介紹一下,還是那句話,看不明白沒關係,以後還會講的!

概念 解釋
Subject 翻譯爲主題、科目。可以想象成雜誌中的板塊吧…
Subscribe 訂閱。可以想象成訂閱雜誌啊…
OnSubscribe 當訂閱的時候要做的事情。可以想象爲當有用戶訂閱的時候開始寫文章…
subscribeOn 做事情所在的線程
Schedulers 調度器。上節有講,用於指定在哪個線程工作,與subscribeOn配套使用
Single 單一的輸入輸出異步任務

RxJava中常見的Subject有4種,分別是AsyncSubject、 BehaviorSubject、 PublishSubject、 ReplaySubject

值得注意的是一定要用Subcect.create()的方式創建並使用,不要用just(T)、from(T)、create(T)創建,否則會導致失效…

值得注意的是我們使用的just()是一種特殊的create(),它不能指定Schedulers。只能在當前線程中運行,而create()可以指定Schedulers實現異步處理。且just()不管是否被subscribe()訂閱均會被調用,而create()如果不被訂閱是不會被調用的。所以我們通常可以用just()傳遞簡單參數,而用create()處理複雜異步邏輯。

AsyncSubject

簡單的說使用AsyncSubject無論輸入多少參數,永遠只輸出最後一個參數。
AS img

// 無論訂閱的時候AsyncSubject是否Completed,均可以收到最後一個值的回調
AsyncSubject as = AsyncSubject.create();
as.onNext(1);
as.onNext(2);
as.onNext(3);
// 這裏訂閱收到3
as.onCompleted();
// 結束後,這裏訂閱也能收到3
as.subscribe(
        new Action1<Integer>() {
            @Override
            public void call(Integer o) {
                LogHelper.e("S:" + o);// 這裏只會輸出3
            }
        });

// 不要這樣使用Subject
AsyncSubject.just(1, 2, 3).subscribe(
        new Action1<Integer>() {
            @Override
            public void call(Integer o) {
                // 這裏會輸出1, 2, 3
                LogHelper.e("S:" + o);
            }
        });
// 因爲just(T)、from(T)、create(T)會把Subject轉換爲Obserable

但是如果因爲發生了錯誤而終止,AsyncSubject將不會發射任何數據,只是簡單的向前傳遞這個錯誤通知。
AS error img

BehaviorSubject

BehaviorSubject會發送離訂閱最近的上一個值,沒有上一個值的時候會發送默認值。看圖
BS img
如果遇到錯誤會直接中斷
BS error img

// 注意訂閱時機,以下這個例子收不到回調
BehaviorSubject bs = BehaviorSubject.create(-1);
// 這裏訂閱回調-1, 1, 2, 3
bs.onNext(1);
// 這裏訂閱回調1, 2, 3
bs.onNext(2);
// 這裏訂閱回調2, 3
bs.onNext(3);
// 這裏訂閱回調3
bs.onCompleted();
// 這裏訂閱沒回調
bs.subscribe(
        new Action1<Integer>() {
            @Override
            public void call(Integer o) {
                LogHelper.e("S:" + o);
            }
        });

PublishSubject

可以說是最正常的Subject,從那裏訂閱就從那裏開始發送數據。
PS img

PublishSubject bs = PublishSubject.create();
// 這裏訂閱接收1, 2, 3
bs.onNext(1);
// 這裏訂閱接收2, 3
bs.onNext(2);
// 這裏訂閱接收3
bs.onNext(3);
bs.onCompleted();
// 這裏訂閱無接收
bs.subscribe(
        new Action1<Integer>() {
            @Override
            public void call(Integer o) {
                LogHelper.e("S:" + o);
            }
        });

ReplaySubject

無論何時訂閱,都會將所有歷史訂閱內容全部發出。

ReplaySubject bs = ReplaySubject.create();
// 無論何時訂閱都會收到1,2,3
bs.onNext(1);
bs.onNext(2);
bs.onNext(3);
bs.onCompleted();
bs.subscribe(
        new Action1<Integer>() {
            @Override
            public void call(Integer o) {
                LogHelper.e("S:" + o);
            }
        });

總結

總的來說Subject沒法指定異步線程,更像是EventBus通過訂閱來實現事件通知。

參考:https://www.jianshu.com/p/1257c8ba7c0c
https://www.cnblogs.com/yongfengnice/p/10229473.html

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