參考:
給 Android 開發(fā)者的 RxJava 詳解-扔物線
深入淺出RxJava
基礎(chǔ)
"a library for composing asynchronous and event-based programs using observable sequences for the Java VM" (一個在 Java VM 上使用可觀測的序列來組成==異步==的、基于事件的程序的庫)
采用函數(shù)響應(yīng)式編程的思想,使異步代碼更簡潔、邏輯更清晰,避免了令人頭痛的回調(diào)的嵌套、線程調(diào)度等問題。
RxJava 的觀察者模式
RxJava 有四個基本概念:Observable (被觀察者)、 Subscriber (觀察者)、 subscribe (訂閱)、事件。
Observable 和 Subscriber 通過 subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系,從而 Observable 可以在需要的時(shí)候發(fā)出事件來通知 Subscriber。
與傳統(tǒng)觀察者模式的區(qū)別是:
- 如果 Observerble 沒有任何的 Subscriber,那么這個 Observable 不會發(fā)出任何事件的。
-
RxJava 的事件回調(diào)方法除了普通事件 onNext() (相當(dāng)于 onClick() / onEvent())之外,還定義了兩個特殊的事件:onCompleted() 和 onError()。
- onCompleted(): 事件隊(duì)列完結(jié)。當(dāng)事件流發(fā)送完畢時(shí),會觸發(fā) onCompleted() 方法。
- onError(): 事件隊(duì)列異常。在事件處理過程中有異常拋出時(shí),onError() 會被觸發(fā),同時(shí)隊(duì)列自動終止,不允許再有事件發(fā)出。(RxJava 不僅把每個事件單獨(dú)處理,還會把它們看做一個隊(duì)列。)
基本實(shí)現(xiàn)
1.創(chuàng)建Observable
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Hi");
subscriber.onNext("Aloha");
subscriber.onCompleted();
}
});
Observable 即被觀察者,它決定什么時(shí)候觸發(fā)事件以及觸發(fā)怎樣的事件。
這里,使用create()
方法來創(chuàng)建一個 Observable,并定義事件觸發(fā)規(guī)則:觀察者Subscriber 將會被調(diào)用三次 onNext()
和一次 onCompleted()
。這里傳入了一個 OnSubscribe 對象作為參數(shù)。OnSubscribe 會被存儲在返回的 Observable 對象中,它的作用相當(dāng)于一個計(jì)劃表,當(dāng) Observable 被訂閱的時(shí)候,OnSubscribe 的 call()
方法會自動被調(diào)用,事件序列就會依照設(shè)定依次觸發(fā)。這樣,由被觀察者調(diào)用了觀察者的回調(diào)方法,就實(shí)現(xiàn)了由被觀察者向觀察者的事件傳遞,即觀察者模式。
create()
方法是 RxJava 最基本的創(chuàng)造事件序列的方法。基于這個方法, RxJava 還提供了一些方法用來快捷創(chuàng)建事件隊(duì)列,例如:
-
just(T...)
: 將傳入的參數(shù)依次發(fā)送出來。 -
from(T[]) / from(Iterable<? extends T>)
: 將傳入的數(shù)組或 Iterable 拆分成具體對象后,依次發(fā)送出來。
Observable observable = Observable.just("Hello", "Hi", "Aloha");
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
這兩段代碼與前面的創(chuàng)建方式等價(jià)。
2.創(chuàng)建Observer
Observer 即觀察者,它決定事件觸發(fā)的時(shí)候?qū)⒂性鯓拥男袨椤?br> RxJava 中的 Observer 接口:
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
此外,RxJava 還內(nèi)置了一個實(shí)現(xiàn)了 Observer、Subscription 的抽象類:Subscriber。
Subscriber 對 Observer 接口進(jìn)行了一些擴(kuò)展:
-
onStart()
: 在 subscribe 剛開始,而事件還未發(fā)送之前被調(diào)用,可以用于做一些準(zhǔn)備工作,例如數(shù)據(jù)的清零或重置。需要注意的是,如果對準(zhǔn)備工作的線程有要求(例如彈出一個顯示進(jìn)度的對話框,這必須在主線程執(zhí)行),onStart()
就不適用了,因?yàn)樗偸窃?subscribe 所發(fā)生的線程被調(diào)用,而不能指定線程。要在指定的線程來做準(zhǔn)備工作,可以使用doOnSubscribe()
方法。 -
unsubscribe()
: 這是 Subscriber 所實(shí)現(xiàn)的另一個接口 Subscription 的方法,用于取消訂閱。在這個方法被調(diào)用后,Subscriber 將不再接收事件。一般在這個方法調(diào)用前,可以使用isUnsubscribed()
先判斷一下狀態(tài)。unsubscribe()
這個方法很重要,因?yàn)樵?subscribe()
之后, Observable 會持有 Subscriber 的引用,這個引用如果不能及時(shí)被釋放,將有內(nèi)存泄露的風(fēng)險(xiǎn)。所以最好保持一個原則:要在不再使用的時(shí)候盡快在合適的地方(例如onPause()``onStop()
等方法中)調(diào)用 unsubscribe() 來解除引用關(guān)系,以避免內(nèi)存泄露的發(fā)生。
3.Subscribe
通過subscribe()方法將被觀察者和觀察者關(guān)聯(lián)起來:
observable.subscribe(subscriber);
內(nèi)部實(shí)現(xiàn)(僅核心代碼):
public Subscription subscribe(Subscriber subscriber) {
subscriber.onStart();
onSubscribe.call(subscriber);
return subscriber;
}
subscribe()
主要做了3件事:
- 調(diào)用
Subscriber.onStart()
,進(jìn)行訂閱前的初始化工作。 - 調(diào)用 Observable 中的
OnSubscribe.call(Subscriber)
。事件發(fā)送的邏輯開始運(yùn)行。可以看到, Observable 并不是在創(chuàng)建的時(shí)候就立即開始發(fā)送事件,而是在它被訂閱的時(shí)候,即當(dāng)subscribe()
方法執(zhí)行的時(shí)候,才開始發(fā)送事件。 - 將傳入的 Subscriber 作為 Subscription 返回,便于解除訂閱
unsubscribe()
.
subscribe過程圖
線程控制
默認(rèn)情況下,事件的發(fā)出和 消費(fèi)都是在同一個線程的。
要實(shí)現(xiàn)『后臺處理,前臺回調(diào)』的異步機(jī)制,可以使用subscribeOn()
和observeOn()
兩個方法,結(jié)合Scheduler,來對線程進(jìn)行控制。
-
subscribeOn()
: 指定subscribe()
所發(fā)生的線程,即Observable.OnSubscribe
被激活時(shí)所處的線程。或者叫做事件產(chǎn)生的線程。 -
observeOn()
: 指定 Subscriber 所運(yùn)行的線程。或者叫做事件消費(fèi)的線程。
RxJava 內(nèi)置的 Scheduler:
-
Schedulers.immediate()
: 直接在當(dāng)前線程運(yùn)行,這是默認(rèn)的 Scheduler。 -
Schedulers.newThread()
: 總是啟用新線程,并在新線程執(zhí)行操作。 -
Schedulers.io()
: I/O 操作(讀寫文件、讀寫數(shù)據(jù)庫、網(wǎng)絡(luò)信息交互等)。行為模式和 newThread() 差不多,區(qū)別在于 io() 的內(nèi)部實(shí)現(xiàn)是使用一個無數(shù)量上限的線程池,可以重用空閑的線程,因此多數(shù)情況下 io() 比 newThread() 更有效率。注意不要把計(jì)算工作放在 io() 線程中,以避免創(chuàng)建不必要的線程。 -
Schedulers.computation()
: 用于 CPU 密集型計(jì)算,即不會被 I/O 等操作限制性能的操作,例如圖形的計(jì)算。這個 Scheduler 使用固定的線程池,大小為 CPU 核數(shù)。注意不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時(shí)間會浪費(fèi) CPU。 -
AndroidSchedulers.mainThread()
:Android 主線程。
示例(適用于多數(shù)的 『后臺線程取數(shù)據(jù),主線程顯示』的程序策略):
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 發(fā)生在 IO 線程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回調(diào)發(fā)生在主線程
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer number) {
Log.d(tag, "number:" + number);
}
});
線程的自用控制:
observeOn() 指定的是 Subscriber 的線程,而這個 Subscriber 并不一定是subscribe() 參數(shù)中的 Subscriber ,而是 observeOn() 執(zhí)行時(shí)的當(dāng)前 Observable 所對應(yīng)的Subscriber ,即它的直接下級 Subscriber 。換句話說,observeOn() 指定的是它之后的操作所在的線程。因此如果有多次切換線程的需求,只要在每個想要切換線程的位置調(diào)用一次 observeOn() 即可。
Observable.just(1, 2, 3, 4) // IO 線程,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新線程,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 線程,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主線程,由 observeOn() 指定
subscribeOn() 和 observeOn() 的內(nèi)部實(shí)現(xiàn),也是基于 lift() 方法。
從圖中可以看出,subscribeOn() 和 observeOn() 都做了線程切換的工作(圖中的 "schedule..." 部位)。不同的是, subscribeOn() 的線程切換發(fā)生在 OnSubscribe 中,即在它通知上一級 OnSubscribe 時(shí),這時(shí)事件還沒有開始發(fā)送,因此 subscribeOn() 的線程控制可以從事件發(fā)出的開端就造成影響;而 observeOn() 的線程切換則發(fā)生在它內(nèi)建的 Subscriber 中,即發(fā)生在它即將給下一級 Subscriber 發(fā)送事件時(shí),因此 observeOn() 控制的是它后面的線程。
多個 subscribeOn() 和 observeOn() 混合使用時(shí),線程調(diào)度的流程圖:
圖中共有 5 處含有對事件的操作。由圖中可以看出,①和②兩處受第一個 subscribeOn() 影響,運(yùn)行在紅色線程;③和④處受第一個 observeOn() 的影響,運(yùn)行在綠色線程;⑤處受第二個 onserveOn() 影響,運(yùn)行在紫色線程;而第二個 subscribeOn() ,由于在通知過程中線程就被第一個 subscribeOn() 截?cái)啵虼藢φ麄€流程并沒有任何影響。這里也就回答了前面的問題:==當(dāng)使用了多個 subscribeOn() 的時(shí)候,只有第一個 subscribeOn() 起作用。==
事件變換
RxJava 提供了對事件序列進(jìn)行變換的支持,這是它的核心功能之一,將事件序列中的對象或整個序列進(jìn)行加工處理,轉(zhuǎn)換成不同的事件或事件序列。
lift:針對事件項(xiàng)和事件序列的變換
map()
、flatMap()
等變換都是基于同一個基礎(chǔ)的變換方法lift(Operator)
的包裝。
lift()
的內(nèi)部實(shí)現(xiàn)(僅核心代碼):
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
return Observable.create(new OnSubscribe<R>() {
@Override
public void call(Subscriber subscriber) {
Subscriber newSubscriber = operator.call(subscriber);
newSubscriber.onStart();
onSubscribe.call(newSubscriber);
}
});
}
1.lift() 創(chuàng)建了一個 Observable 后,加上之前的原始 Observable,已經(jīng)有兩個 Observable 了;
2.而同樣地,新 Observable 里的新 OnSubscribe 加上之前的原始 Observable 中的原始 OnSubscribe,也就有了兩個 OnSubscribe;
3.當(dāng)用戶調(diào)用經(jīng)過 lift() 后的 Observable 的 subscribe() 的時(shí)候,使用的是 lift() 所返回的新的 Observable ,于是它所觸發(fā)的 onSubscribe.call(subscriber),也是用的新 Observable 中的新 OnSubscribe,即在 lift() 中生成的那個 OnSubscribe;
4.而這個新 OnSubscribe 的 call() 方法中的 onSubscribe ,就是指的原始 Observable 中的原始 OnSubscribe ,在這個 call() 方法里,新 OnSubscribe 利用 operator.call(subscriber) 生成了一個新的 Subscriber(Operator 就是在這里,通過自己的 call() 方法將新 Subscriber 和原始 Subscriber 進(jìn)行關(guān)聯(lián),并插入自己的『變換』代碼以實(shí)現(xiàn)變換),然后利用這個新 Subscriber 向原始 Observable 進(jìn)行訂閱。
這樣就實(shí)現(xiàn)了 lift() 過程,有點(diǎn)像一種代理機(jī)制,通過事件攔截和處理實(shí)現(xiàn)事件序列的變換。
簡而言之,在 Observable 執(zhí)行了 lift(Operator) 方法之后,會返回一個新的 Observable,這個新的 Observable 會像一個代理一樣,負(fù)責(zé)接收原始的 Observable 發(fā)出的事件,并在處理后發(fā)送給 Subscriber。
兩次和多次的 lift() 同理:
示例:將事件中的 Integer 對象轉(zhuǎn)換成 String
observable.lift(new Observable.Operator<String, Integer>() {
@Override
public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
// 將事件序列中的 Integer 對象轉(zhuǎn)換為 String 對象
return new Subscriber<Integer>() {
@Override
public void onNext(Integer integer) {
subscriber.onNext("" + integer);
}
@Override
public void onCompleted() {
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
subscriber.onError(e);
}
};
}
});
compose: 對 Observable 整體的變換
它和 lift() 的區(qū)別在于, lift() 是針對事件項(xiàng)和事件序列的,而 compose() 是針對 Observable 自身進(jìn)行變換。
示例:
假設(shè)在程序中有多個 Observable ,并且他們都需要應(yīng)用一組相同的 lift() 變換。你可以這么寫:
observable1
.lift1()
.lift2()
.lift3()
.lift4()
.subscribe(subscriber1);
observable2
.lift1()
.lift2()
.lift3()
.lift4()
.subscribe(subscriber2);
observable3
.lift1()
.lift2()
.lift3()
.lift4()
.subscribe(subscriber3);
observable4
.lift1()
.lift2()
.lift3()
.lift4()
.subscribe(subscriber1);
這樣代碼復(fù)用性太差,于是改寫成:
private Observable liftAll(Observable observable) {
return observable
.lift1()
.lift2()
.lift3()
.lift4();
}
...
liftAll(observable1).subscribe(subscriber1);
liftAll(observable2).subscribe(subscriber2);
liftAll(observable3).subscribe(subscriber3);
liftAll(observable4).subscribe(subscriber4);
可讀性、可維護(hù)性都提高了。可是 Observable 被一個方法包起來,如果后期需求變化,observable1在進(jìn)行l(wèi)iftAll()變換前需要先進(jìn)行l(wèi)ift5()變換,就打破了api的鏈?zhǔn)秸{(diào)用,這種方式對于 Observale 的靈活性增添了限制。此時(shí),就可以用 compose() 來解決:
public class LiftAllTransformer implements Observable.Transformer<Integer, String> {
@Override
public Observable<String> call(Observable<Integer> observable) {
return observable
.lift1()
.lift2()
.lift3()
.lift4();
}
}
...
Transformer liftAll = new LiftAllTransformer();
observable1.compose(liftAll).subscribe(subscriber1);
observable2.compose(liftAll).subscribe(subscriber2);
observable3.compose(liftAll).subscribe(subscriber3);
observable4.compose(liftAll).subscribe(subscriber4);
操作符
創(chuàng)建操作
- Create — 通過調(diào)用觀察者的方法從頭創(chuàng)建一個Observable
- Defer — 在觀察者訂閱之前不創(chuàng)建這個Observable,為每一個觀察者創(chuàng)建一個新的Observable
- Empty/Never/Throw — 創(chuàng)建行為受限的特殊Observable
- From — 將其它的對象或數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為Observable
- Interval — 創(chuàng)建一個定時(shí)發(fā)射整數(shù)序列的Observable
- Just — 將對象或者對象集合轉(zhuǎn)換為一個會發(fā)射這些對象的Observable
- Range — 創(chuàng)建發(fā)射指定范圍的整數(shù)序列的Observable
- Repeat — 創(chuàng)建重復(fù)發(fā)射特定的數(shù)據(jù)或數(shù)據(jù)序列的Observable
- Start — 創(chuàng)建發(fā)射一個函數(shù)的返回值的Observable
- Timer — 創(chuàng)建在一個指定的延遲之后發(fā)射單個數(shù)據(jù)的Observable
變換操作
- Buffer — 緩存,可以簡單的理解為緩存,它定期從Observable收集數(shù)據(jù)到一個集合,然后把這些數(shù)據(jù)集合打包發(fā)射,而不是一次發(fā)射一個
- FlatMap — 扁平映射,將Observable發(fā)射的數(shù)據(jù)變換為Observables集合,然后將這些Observable發(fā)射的數(shù)據(jù)平坦化的放進(jìn)一個單獨(dú)的Observable,可以認(rèn)為是一個將嵌套的數(shù)據(jù)結(jié)構(gòu)展開的過程。
- GroupBy — 分組,將原來的Observable分拆為Observable集合,將原始Observable發(fā)射的數(shù)據(jù)按Key分組,每一個Observable發(fā)射一組不同的數(shù)據(jù)
- Map — 映射,通過對序列的每一項(xiàng)都應(yīng)用一個函數(shù)變換Observable發(fā)射的數(shù)據(jù),實(shí)質(zhì)是對序列中的每一項(xiàng)執(zhí)行一個函數(shù),函數(shù)的參數(shù)就是這個數(shù)據(jù)項(xiàng)
- Scan — 掃描,對Observable發(fā)射的每一項(xiàng)數(shù)據(jù)應(yīng)用一個函數(shù),然后按順序依次發(fā)射這些值
- Window — 窗口,定期將來自O(shè)bservable的數(shù)據(jù)分拆成一些Observable窗口,然后發(fā)射這些窗口,而不是每次發(fā)射一項(xiàng)。類似于Buffer,但Buffer發(fā)射的是數(shù)據(jù),Window發(fā)射的是Observable,每一個Observable發(fā)射原始Observable的數(shù)據(jù)的一個子集
過濾操作
- Debounce — 只有在空閑了一段時(shí)間后才發(fā)射數(shù)據(jù),通俗的說,就是如果一段時(shí)間沒有操作,就執(zhí)行一次操作
- Distinct — 去重,過濾掉重復(fù)數(shù)據(jù)項(xiàng)
- ElementAt — 取值,取特定位置的數(shù)據(jù)項(xiàng)
- Filter — 過濾,過濾掉沒有通過謂詞測試的數(shù)據(jù)項(xiàng),只發(fā)射通過測試的
- First — 首項(xiàng),只發(fā)射滿足條件的第一條數(shù)據(jù)
- IgnoreElements — 忽略所有的數(shù)據(jù),只保留終止通知(onError或onCompleted)
- Last — 末項(xiàng),只發(fā)射最后一條數(shù)據(jù)
- Sample — 取樣,定期發(fā)射最新的數(shù)據(jù),等于是數(shù)據(jù)抽樣,有的實(shí)現(xiàn)里叫ThrottleFirst
- Skip — 跳過前面的若干項(xiàng)數(shù)據(jù)
- SkipLast — 跳過后面的若干項(xiàng)數(shù)據(jù)
- Take — 只保留前面的若干項(xiàng)數(shù)據(jù)
- TakeLast — 只保留后面的若干項(xiàng)數(shù)據(jù)
組合操作
- And/Then/When — 通過模式(And條件)和計(jì)劃(Then次序)組合兩個或多個Observable發(fā)射的數(shù)據(jù)集
- CombineLatest — 當(dāng)兩個Observables中的任何一個發(fā)射了一個數(shù)據(jù)時(shí),通過一個指定的函數(shù)組合每個Observable發(fā)射的最新數(shù)據(jù)(一共兩個數(shù)據(jù)),然后發(fā)射這個函數(shù)的結(jié)果
- Join — 無論何時(shí),如果一個Observable發(fā)射了一個數(shù)據(jù)項(xiàng),只要在另一個Observable發(fā)射的數(shù)據(jù)項(xiàng)定義的時(shí)間窗口內(nèi),就將兩個Observable發(fā)射的數(shù)據(jù)合并發(fā)射
- Merge — 將兩個Observable發(fā)射的數(shù)據(jù)組合并成一個
- StartWith — 在發(fā)射原來的Observable的數(shù)據(jù)序列之前,先發(fā)射一個指定的數(shù)據(jù)序列或數(shù)據(jù)項(xiàng)
- Switch — 將一個發(fā)射Observable序列的Observable轉(zhuǎn)換為這樣一個Observable:它逐個發(fā)射那些Observable最近發(fā)射的數(shù)據(jù)
- Zip — 打包,使用一個指定的函數(shù)將多個Observable發(fā)射的數(shù)據(jù)組合在一起,然后將這個函數(shù)的結(jié)果作為單項(xiàng)數(shù)據(jù)發(fā)射
錯誤處理
這些操作符用于從錯誤通知中恢復(fù):
- Catch — 捕獲,繼續(xù)序列操作,將錯誤替換為正常的數(shù)據(jù),從onError通知中恢復(fù)
- Retry — 重試,如果Observable發(fā)射了一個錯誤通知,重新訂閱它,期待它正常終止
輔助操作
- Delay — 延遲一段時(shí)間發(fā)射結(jié)果數(shù)據(jù)
- Do — 注冊一個動作占用一些Observable的生命周期事件,相當(dāng)于Mock某個操作
- Materialize/Dematerialize — 將發(fā)射的數(shù)據(jù)和通知都當(dāng)做數(shù)據(jù)發(fā)射,或者反過來
- ObserveOn — 指定觀察者觀察Observable的調(diào)度程序(工作線程)
- Serialize — 強(qiáng)制Observable按次序發(fā)射數(shù)據(jù)并且功能是有效的
- Subscribe — 收到Observable發(fā)射的數(shù)據(jù)和通知后執(zhí)行的操作
- SubscribeOn — 指定Observable應(yīng)該在哪個調(diào)度程序上執(zhí)行
- TimeInterval — 將一個Observable轉(zhuǎn)換為發(fā)射兩個數(shù)據(jù)之間所耗費(fèi)時(shí)間的Observable
- Timeout — 添加超時(shí)機(jī)制,如果過了指定的一段時(shí)間沒有發(fā)射數(shù)據(jù),就發(fā)射一個錯誤通知
- Timestamp — 給Observable發(fā)射的每個數(shù)據(jù)項(xiàng)添加一個時(shí)間戳
- Using — 創(chuàng)建一個只在Observable的生命周期內(nèi)存在的一次性資源
條件和布爾操作
這些操作符可用于單個或多個數(shù)據(jù)項(xiàng),也可用于Observable。
- All — 判斷Observable發(fā)射的所有的數(shù)據(jù)項(xiàng)是否都滿足某個條件
- Amb — 給定多個Observable,只讓第一個發(fā)射數(shù)據(jù)的Observable發(fā)射全部數(shù)據(jù)
- Contains — 判斷Observable是否會發(fā)射一個指定的數(shù)據(jù)項(xiàng)
- DefaultIfEmpty — 發(fā)射來自原始Observable的數(shù)據(jù),如果原始Observable沒有發(fā)射數(shù)據(jù),就發(fā)射一個默認(rèn)數(shù)據(jù)
- SequenceEqual — 判斷兩個Observable是否按相同的數(shù)據(jù)序列
- SkipUntil — 丟棄原始Observable發(fā)射的數(shù)據(jù),直到第二個Observable發(fā)射了一個數(shù)據(jù),然后發(fā)射原始Observable的剩余數(shù)據(jù)
- SkipWhile — 丟棄原始Observable發(fā)射的數(shù)據(jù),直到一個特定的條件為假,然后發(fā)射原始Observable剩余的數(shù)據(jù)
- TakeUntil — 發(fā)射來自原始Observable的數(shù)據(jù),直到第二個Observable發(fā)射了一個數(shù)據(jù)或一個通知
- TakeWhile — 發(fā)射原始Observable的數(shù)據(jù),直到一個特定的條件為真,然后跳過剩余的數(shù)據(jù)
算術(shù)和聚合操作
這些操作符可用于整個數(shù)據(jù)序列
- Average — 計(jì)算Observable發(fā)射的數(shù)據(jù)序列的平均值,然后發(fā)射這個結(jié)果
- Concat — 不交錯的連接多個Observable的數(shù)據(jù)
- Count — 計(jì)算Observable發(fā)射的數(shù)據(jù)個數(shù),然后發(fā)射這個結(jié)果
- Max — 計(jì)算并發(fā)射數(shù)據(jù)序列的最大值
- Min — 計(jì)算并發(fā)射數(shù)據(jù)序列的最小值
- Reduce — 按順序?qū)?shù)據(jù)序列的每一個應(yīng)用某個函數(shù),然后返回這個值
- Sum — 計(jì)算并發(fā)射數(shù)據(jù)序列的和
連接操作
一些有精確可控的訂閱行為的特殊Observable
- Connect — 指示一個可連接的Observable開始發(fā)射數(shù)據(jù)給訂閱者
- Publish — 將一個普通的Observable轉(zhuǎn)換為可連接的
- RefCount — 使一個可連接的Observable表現(xiàn)得像一個普通的Observable
- Replay — 確保所有的觀察者收到同樣的數(shù)據(jù)序列,即使他們在Observable開始發(fā)射數(shù)據(jù)之后才訂閱
轉(zhuǎn)換操作
- To — 將Observable轉(zhuǎn)換為其它的對象或數(shù)據(jù)結(jié)構(gòu)
- Blocking - 阻塞Observable的操作符
使用場景
- 與 Retrofit 的結(jié)合
- RxBinding
- 各種異步操作
- RxBus
其他
subscribe()不完整定義的回調(diào),Action、Function接口
doOnSubscribe()
Subscriber 的 onStart() 可以用作流程開始前的初始化。然而 onStart() 由于在 subscribe() 發(fā)生時(shí)就被調(diào)用了,因此不能指定線程,而是只能執(zhí)行在 subscribe() 被調(diào)用時(shí)的線程。這就導(dǎo)致如果 onStart() 中含有對線程有要求的代碼(例如在界面上顯示一個 ProgressBar,這必須在主線程執(zhí)行),將會有線程非法的風(fēng)險(xiǎn),因?yàn)橛袝r(shí)你無法預(yù)測 subscribe() 將會在什么線程執(zhí)行。
而與 Subscriber.onStart() 相對應(yīng)的,有一個方法 Observable.doOnSubscribe() 。它和 Subscriber.onStart() 同樣是在 subscribe() 調(diào)用后而且在事件發(fā)送前執(zhí)行,但區(qū)別在于它可以指定線程。默認(rèn)情況下, doOnSubscribe() 執(zhí)行在 subscribe() 發(fā)生的線程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的話,它將執(zhí)行在離它最近的 subscribeOn() 所指定的線程。
Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 需要在主線程執(zhí)行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主線程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);