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無論輸入多少參數,永遠只輸出最後一個參數。
// 無論訂閱的時候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將不會發射任何數據,只是簡單的向前傳遞這個錯誤通知。
BehaviorSubject
BehaviorSubject會發送離訂閱最近的上一個值,沒有上一個值的時候會發送默認值。看圖
如果遇到錯誤會直接中斷
// 注意訂閱時機,以下這個例子收不到回調
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,從那裏訂閱就從那裏開始發送數據。
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