Kotlin 使用Rxjava的compose()操作符
轉載
在RXJava中一種比較nice的思想是能夠通過一系列的操作符看到資料是如何轉換的:
Observable.from(someSource)
.map(data -> manipulate(data))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> doSomething(data));
假設想要給多個流重複利用一系列操作符該怎麼辦呢?比如,我想在工作執行緒中處理資料,在主執行緒中訂閱,所以必須頻繁使用subscribeOn() 和observeOn()。如果我能將這邏輯通過連續的、可重複的方式應用到我的所有流上,那簡直太棒了。
壞方法
下面這個方法是我用過數月的“反模式”方法。首先,建立一個方法,該方法適用於排程器
<T> Observable<T> applySchedulers(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
然後呼叫applySchedulers(),包裝你的Observable鏈:
applySchedulers(
Observable.from(someSource)
.map(data -> manipulate(data))
)
.subscribe(data -> doSomething(data));
雖然這樣寫能執行但是很醜很亂——因為applySchedulers()導致了它不再是操作符,因此很難在其後面追加其他操作符。現在,當你多用幾次這種“反模式”在單一流上之後你就會覺得它有多壞了。
Transformers登場
在RXJava背後有一群聰明的人意識到了這是一個問題並且提供瞭解決方案:Transformer ,它和 Observable.compose() 一起使用。
Transformer實際上就是Func1<Observable , Observable
,換句話說就是提供給他一個Observable它會返回給你另一個Observable,這和內聯一系列操作符有著同等功效。
實際操作下,寫個方法,建立一個Transformer排程器:
<T> Transformer<T, T> applySchedulers() {
return new Transformer<T, T>() {
@Override
public Observable<T> call(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
用lambda表示式看上去會好看些:
<T> Transformer<T, T> applySchedulers() {
return observable -> observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
現在呼叫這個方法會是怎麼樣的呢:
Observable.from(someSource)
.map(data -> manipulate(data))
.compose(applySchedulers())
.subscribe(data -> doSomething(data));
是不是好很多!我們既重用了程式碼又保護了鏈式。如果你用的是JDK 7以下版本,你不得不利用compose() 做一些多餘的工作。比如說,你得告訴編譯器返回的型別,像這樣:
Observable.from(someSource)
.map(data -> manipulate(data))
.compose(this.<YourType>applySchedulers())
.subscribe(data -> doSomething(data));
複用Transformers
如果你經常做從一個具體型別轉換到另一個型別來建立一個例項:
Transformer<String, String> myTransformer = new Transformer<String, String>() {
// 幹一些事情
};
用Transformer會怎麼樣呢?它壓根就不會考慮型別問題,但你不能定義一個通用的例項。
你可以把它改成Transformer<Object, Object>,但是返回的Observable會丟失它的型別資訊。
解決這個問題我是從 Collections 中得到了靈感,Collections是一堆型別安全、不可變的空集合的生成方法(比如 Collections.emptyList() )。本質上它採用了非泛型例項,然後通過方法包裹附加泛型資訊。
final Transformer schedulersTransformer =
observable -> observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
@SuppressWarnings("unchecked")
<T> Transformer<T, T> applySchedulers() {
return (Transformer<T, T>) schedulersTransformer;
}
警告:無論如何你都有可能陷入型別轉換異常的坑。確保你的Transformer真的是型別無關的。另一方面,你可能會在執行時丟擲ClassCastException異常,即使你的程式碼編譯通過了。在這個例子裡面,因為排程器沒有和發射的專案發生互動,所以它是型別安全的。
和flatMap()有啥區別?
compose()和flatMap()有啥區別呢。他們都是發射出Observable
,是不是就是說他們都可以複用一系列操作符呢?
區別在於compose()是高等級的抽象,他操作的是整個流,而不是單一發射出的專案,這裡有更多的解釋:
- compose()
是唯一一個能從流中獲取原生Observable 的方法,因此,影響整個流的操作符(像subscribeOn()和observeOn())需要使用compose(),相對的,如果你在flatMap()中使用subscribeOn()/observeOn(),它隻影響你建立的flatMap()中的Observable,而不是整個流。 - 當你建立一個Observable流並且內聯了一堆操作符以後,compose()會立即執行,flatMap()則是在onNext()被呼叫以後才會執行,換句話說,flatMap()轉換的是每個專案,而compose()轉換的是整個流。
- flatMap()一定是低效率的,因為他每次呼叫onNext()之後都需要建立一個新的Observable,compose()是操作在整個流上的。
如果你想用可重用的程式碼替換一些操作符,可以利用compose()和flatMap(),但他們不是唯一的解決辦法。
相關文章
- RxJava常用操作符官方文件翻譯及Kotlin示例(1)RxJavaKotlin
- kotlin 的Elvis 操作符Kotlin
- 3章 RxJava操作符RxJava
- RxJava操作符之組合操作符(六)RxJava
- part05_Rxjava操作符RxJava
- 解剖 RxJava 之變換操作符RxJava
- RxJava2 操作符總結RxJava
- RxJava2.0——變換操作符RxJava
- RxJava 學習筆記 -- 條件操作符和布林操作符RxJava筆記
- Android開發中的Kotlin Coroutine VS RxJavaAndroidKotlinRxJava
- RxJava2操作符學習筆記RxJava筆記
- RxJava 學習筆記 -- 變換操作符RxJava筆記
- RxJava 學習筆記 -- 過濾操作符RxJava筆記
- Android使用Kotlin+Retrofit+Rxjava實現簡單的網路請求AndroidKotlinRxJava
- RxJava2原始碼分析(二):操作符原理分析RxJava原始碼
- RxJava 原始碼分析系列(四) -操作符變換原理RxJava原始碼
- RxJava2.X 學習筆記 -- 建立操作符RxJava筆記
- 【譯】使用Kotlin和RxJava測試MVP架構的完整示例 – 第2部分KotlinRxJavaMVP架構
- Docker compose的使用Docker
- Android Compose 的使用Android
- 忘記Rxjava吧,你應該試試Kotlin的協程RxJavaKotlin
- Rxjava 2.x 原始碼系列 - 變換操作符 Map(上)RxJava原始碼
- 使用 Kotlin + WebFlux/RxJava 2 實現響應式以及嘗試正式版本的協程KotlinWebUXRxJava
- 大話RxJava:三、RxJava的中級使用方法RxJava
- rxjava回撥地獄-kotlin協程來幫忙RxJavaKotlin
- 【填坑往事】使用Rxjava2的distinct操作符處理自定義資料型別去重的問題RxJava資料型別
- RxJava從入門到不離不棄(四)——過濾操作符RxJava
- Kotlin——高階篇(五):集合之常用操作符彙總Kotlin
- Android RxJava: 這是一份全面的 操作符 使用匯總 (含詳細例項講解)AndroidRxJava
- kotlin的Gson的使用Kotlin
- XTask與RxJava的使用比較RxJava
- PHP goto操作符使用PHPGo
- kotlin的迴圈使用Kotlin
- RxJava 系列-3:使用 SubjectRxJava
- 2章 RxJava基本使用RxJava
- RxJava基礎使用(一)RxJava
- (仿有道精品課)RxJava+OkHttp+Retrofit+Dagger2+MVP框架(kotlin版本)RxJavaHTTPMVP框架Kotlin
- kotlin之泛型的使用Kotlin泛型