參考自:
- http://www.jianshu.com/p/464fa025229e (強烈推薦,連載!!!)
- http://blog.csdn.net/jdsjlzx/article/details/51685769
1.Disposable
這個單詞的字面意思是一次性用品,用完即可丟棄的. 那麼在RxJava中怎麼去理解它呢, 對應於上面的水管的例子, 我們可以把它理解成兩根管道之間的一個機關, 當調用它的dispose()方法時, 它就會將兩根管道切斷,從而導致下游收不到事件.
注意:調用dispose()並不會導致上游不再繼續發送事件, 上游會繼續發送剩餘的事件,但下游不會再接收事件onComplete和onError都不會走了。
那怎麼才能在dispose()之後上游也不發送事件了呢?
調用dispose()方法時就會切斷水管, 使得下游收不到事件, 既然收不到事件, 那麼也就不會再去更新UI了. 因此我們可以在Activity中將這個Disposable 保存起來, 當Activity退出時, 切斷它即可;使用MVP的話,在onDestroy裏調用presenter/model裏的方法切斷。
那如果有多個Disposable 該怎麼辦呢, RxJava中已經內置了一個容器CompositeDisposable, 每當我們得到一個Disposable時就調用CompositeDisposable.add()將它添加到容器中, 在退出的時候, 調用CompositeDisposable.clear() 即可切斷所有的水管.
Observable.just("Kobe", "Curry")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
JustActivity.this.d = d;
txt.append("onSubscribe d.isDisposed " + d.isDisposed() + "\n");
}
@Override
public void onNext(String s) {
txt.append("onNext " + s + "\n");
d.dispose();
txt.append("onNext d.isDisposed " + d.isDisposed() + "\n");
}
@Override
public void onError(Throwable e) {
txt.append("onError" + e.getMessage() + "\n");
}
@Override
public void onComplete() {
txt.append("onComplete" + "\n");
}
});
輸出的結果是:
onSubscribe d.isDisposed false
onNext Kobe
onNext d.isDisposed true
2.ObservableEmitter
Emitter是發射器的意思,那就很好猜了,這個就是用來發出事件的,它可以發出三種類型的事件,通過調用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事件會導致程序會崩潰.
Observable.create(new ObservableOnSubscribe<FirstType>() {
@Override
public void subscribe(ObservableEmitter<FirstType> e) throws Exception {
Log.d("test", "subscribe " + e.isDisposed());
//運行在後臺線程,子線程不能動態更新UI,這行代碼會出錯
//txt.append("subscribe " + e.isDisposed() + "\n");
if (!e.isDisposed()) {
e.onNext(new FirstType("James"));
e.onNext(new FirstType("Durant"));
e.onComplete();
}
}
})
//在後臺線程上運行 主要改變的是訂閱的線程,subscribe()執行的線程
.subscribeOn(Schedulers.io())
//在主線程上通知 主要改變的是發送的線程,onNext()執行的線程
.observeOn(AndroidSchedulers.mainThread())
.map(new Function<FirstType, SecondType>() {
@Override
public SecondType apply(@NonNull FirstType firstType) throws Exception {
return new SecondType(firstType.FirstName);
}
})
.subscribe(new Observer<SecondType>() {
@Override
public void onSubscribe(Disposable d) {
txt.append("onSubscribe " + d.isDisposed() + "\n");
Log.d("test", "onSubscribe d.isDisposed() " + d.isDisposed());
}
@Override
public void onNext(SecondType secondType) {
txt.append("onNext " + secondType.secondName + "\n");
Log.d("test", "onNext " + secondType.secondName);
}
@Override
public void onError(Throwable e) {
txt.append("onError" + "\n");
Log.d("test", "onError " + e.getMessage());
}
@Override
public void onComplete() {
txt.append("onComplete" + "\n");
Log.d("test", "onComplete ");
}
});
運行結果:
//可見onSubscribe方法最先被調用
onSubscribe d.isDisposed() false
subscribe false
onNext James
onNext Durant
onComplete
3.在RxJava中, 已經內置了很多線程選項供我們選擇
例如有
- Schedulers.io() 代表io操作的線程, 通常用於網絡,讀寫文件等io密集型的操作
- Schedulers.computation() 代表CPU計算密集型的操作, 例如需要大量計算的操作
- Schedulers.newThread() 代表一個常規的新線程
- AndroidSchedulers.mainThread() 代表Android的主線程
這些內置的Scheduler已經足夠滿足我們開發的需求, 因此我們應該使用內置的這些選項, 在RxJava內部使用的是線程池來維護這些線程, 所以效率也比較高.
4.每十秒請求一次數據
/*
* interval的三個參數
* long period, TimeUnit unit, Scheduler scheduler
* period 在發射第一個值之前等待的初始延遲時間
* unit 間隔大小
* scheduler 時間單位
*/
Observable.interval(0, 10, TimeUnit.SECONDS)
.flatMap(new Function<Long, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(Long aLong) throws Exception {
return null;//這裏放網絡請求
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
}
});