RxJava 以「觀察者模式 + 操作符鏈」重塑異步編程體驗。本文先拆解 Observable.create/subscribe 底層流程,再列舉 Android/後端開發中六大高頻場景的 RxJava 解決方案。
OnSubscribe 回調。onNext/onError/onCompleted。unsubscribe() 取消。// 1. 創建 Observable,保存 onSubscribe 回調
Observable.create(onSubscriber1) // 返回 Observable 實例 observable1
// 2. 訂閱
observable1.subscribe(subscriber1)
// 內部調用:hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber)
// 即:onSubscriber1.call(subscriber1) → 觸發 onNext/onCompleted
本質:Observable 只是「配方」,subscribe 才真正「開火」,實現惰性求值。
需求:任一級命中即終止後續查詢。
方案:Observable.concat(memory, disk, network).first()。concat 保證順序串行,first() 取首個發射項後自動取消後續。
Observable.concat(
Observable.create(s -> { if (memCache!=null) s.onNext(memCache); else s.onCompleted(); }),
Observable.create(s -> { String disk = ...; if (!empty) s.onNext(disk); else s.onCompleted(); }),
Observable.just("network")
).first()
.subscribeOn(Schedulers.io())
.subscribe(s -> { /* 使用數據 */ });
方案:Observable.merge(api1, api2, ...) 合併流,不保證順序,誰先完成誰先發射。配合 toList() 或 zip 聚合結果。
Observable.merge(
api1.subscribeOn(Schedulers.io()),
api2.subscribeOn(Schedulers.io())
).subscribeOn(Schedulers.io())
.subscribe(result -> { /* 更新 UI */ });
痛點:傳統回調嵌套導致「Callback Hell」。
方案:flatMap 將上游發射項轉換為新 Observable 並扁平化合併。
NetworkService.getToken("user", "pass")
.flatMap(token -> NetworkService.getMessage(token))
.subscribe(msg -> { /* 顯示消息 */ });
方案:RxView.clicks(btn).throttleFirst(1, TimeUnit.SECONDS)。throttleFirst:每個時間窗口只取首次事件,其餘丟棄;對比 debounce(靜默期後取最後一次)。
方案:RxCompoundButton.checkedChanges(cb).subscribe(rxPref.getBoolean("key").asAction())。
RxPreferences 將 Preference 封裝為 Action,實現雙向綁定。
同理適用: RxTextView.textChanges、RxAdapterView.itemClicks 等。
Observable.just("1","2","2","3","4","5")
.map(Integer::parseInt)
.filter(i -> i > 1)
.distinct()
.take(3)
.reduce((a,b) -> a + b) // 2+3+4=9
.subscribe(System.out::println);
操作符鏈將命令式迴圈轉為聲明式流水線,可讀性與可組合性大增。
| 類別 | 代表操作符 | 用途 |
|---|---|---|
| 創建 | just, from, create, interval, timer | 構建事件源 |
| 變換 | map, flatMap, concatMap, switchMap | 項目轉換/流扁平化 |
| 過濾 | filter, take, skip, distinct, debounce, throttleFirst | 控制發射項通過 |
| 合併 | merge, concat, zip, combineLatest, join | 多流組合 |
| 聚合 | reduce, collect, count, toList, toMap | 歸約為單值/集合 |
| 副作用 | doOnNext, doOnError, doOnCompleted, doOnSubscribe | 側寫日誌/緩存/埋點 |
| 調度 | subscribeOn, observeOn | 指定上游/下游線程 |
subscribeOn 決定上游(創建端)線程,observeOn 決定下游(消費端)線程,可多次切換。compositeDisposable.clear() 取消訂閱,防止持有 Context。Flowable 支持背壓,高速產生/慢速消費場景必用。onErrorResumeNext/retry/retryWhen 實現降級重試,避免流中斷。RxJava 學習曲線陡峭,但掌握核心「流+操作符」思維後,能將複雜異步邏輯化繁為簡。