本文介紹RxJava中Subject的使用。小白同學(xué)們看清楚并記好了,這里講的是Subject,不是Subscribe,不是Subscription,不是subscribeOn,不是OnSubscribe,不是Schedulers,更不是Single,而是Subject!
這么多S開頭的的單詞有沒有把你弄糊涂啊,英語好的同學(xué)可以略過這段。這里把RxJava中容易和Subject弄混的概念都拿出來介紹一下,還是那句話,看不明白沒關(guān)系,以后還會講的!
| 概念 | 解釋 |
|---|---|
| Subject | 翻譯為主題、科目。可以想象成雜志中的板塊吧.... |
| Subscribe | 訂閱??梢韵胂蟪捎嗛嗠s志啊... |
| OnSubscribe | 當(dāng)訂閱的時候要做的事情??梢韵胂鬄楫?dāng)有用戶訂閱的時候開始寫文章.... |
| subscribeOn | 做事情所在的線程 |
| Schedulers | 調(diào)度器。上節(jié)有講,用于指定在哪個線程工作,與subscribeOn配套使用 |
| Single | 單一的輸入輸出異步任務(wù) |
RxJava中常見的Subject有4種,分別是** AsyncSubject、 BehaviorSubject、 PublishSubject、 ReplaySubject**。
值得注意的是一定要用Subcect.create()的方式創(chuàng)建并使用,不要用just(T)、from(T)、create(T)創(chuàng)建,否則會導(dǎo)致失效...
AsyncSubject
簡單的說使用AsyncSubject無論輸入多少參數(shù),永遠只輸出最后一個參數(shù)。

// 無論訂閱的時候AsyncSubject是否Completed,均可以收到最后一個值的回調(diào)
AsyncSubject as = AsyncSubject.create();
as.onNext(1);
as.onNext(2);
as.onNext(3);
// 這里訂閱收到3
as.onCompleted();
// 結(jié)束后,這里訂閱也能收到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轉(zhuǎn)換為Obserable
但是如果因為發(fā)生了錯誤而終止,AsyncSubject將不會發(fā)射任何數(shù)據(jù),只是簡單的向前傳遞這個錯誤通知。

BehaviorSubject
BehaviorSubject會發(fā)送離訂閱最近的上一個值,沒有上一個值的時候會發(fā)送默認(rèn)值。看圖

如果遇到錯誤會直接中斷

// 注意訂閱時機,以下這個例子收不到回調(diào)
BehaviorSubject bs = BehaviorSubject.create(-1);
// 這里訂閱回調(diào)-1, 1, 2, 3
bs.onNext(1);
// 這里訂閱回調(diào)1, 2, 3
bs.onNext(2);
// 這里訂閱回調(diào)2, 3
bs.onNext(3);
// 這里訂閱回調(diào)3
bs.onCompleted();
// 這里訂閱沒回調(diào)
bs.subscribe(
new Action1<Integer>() {
@Override
public void call(Integer o) {
LogHelper.e("S:" + o);
}
});
PublishSubject
可以說是最正常的Subject,從那里訂閱就從那里開始發(fā)送數(shù)據(jù)。

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
無論何時訂閱,都會將所有歷史訂閱內(nèi)容全部發(fā)出。
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);
}
});
總結(jié)
總的來說Subject沒法指定異步線程,更像是EventBus通過訂閱來實現(xiàn)事件通知。
下一篇文章我們會介紹Scheduler調(diào)度器