RxJava 基礎知識
RxJava 學習筆記 -- 變換操作符
操作符 | 作用 |
---|---|
map() | 對序列的每一項都用一個函式來變換Observable發射的資料序列 |
flatMap() | 將Observable發射的資料集合變換為Observables集合,然後將這些Observable發射的資料平坦化的放進一個單獨的Observable中 |
switchMap() | 將Observable發射的資料集合變化成Observable集合,然後只發射這些Observables 最近發射過的資料 |
scan() | 對Observable發射的每一項資料應用一個函式,然後按順序依次發射每一個值 |
groupBy() | 將Observable拆分為Observable 集合,將原始Observable發射的資料按Key分組,每一個Observable發射一組不同的資料 |
buffer() | 定期從Observable收集資料到一個集合,然後把這些資料集合打包發射,而不是一次發射一個 |
window() | 定期將來自Observable的資料拆分成一些Observable視窗,然後發射這些視窗,而不是每次發射一項 |
cast() | 在發射之前強制將Observable發射的所有資料裝換為指定型別 |
下面只列舉一些常用的變換操作符的用法:
一. Map
對Observable發射的每一項資料應用一個函式,執行變換操作
fun testMap(){
Observable.just("HELLO")
.map {
//把大寫轉換成小寫
it.toLowerCase()
}
.map {
//新增新的字串
"$it MuFeng!"
}
.subscribeBy { Log.e("TAG",it) }
}
複製程式碼
執行結果
09-07 03:01:11.820 9704-9704/com.mufeng.rxjavademo E/TAG: hello MuFeng!
複製程式碼
二. FlatMap
flatMap將一個發射資料的Observable變換為多個Observables,然後將他們發射的資料合併後放進一個單獨的Observable
實際應用:
場景: 列印使用者的所掌握的開發語言
- 我們需要先建立一個使用者的資料類
data class User(var name: String, var languages: ArrayList<Language>)
data class Language(var name: String)
複製程式碼
- 我們分別用map和flatMap來實現
fun testFlatMap() {
val language1 = Language("Android")
val language2 = Language("Java")
val language3 = Language("Kotlin")
val language4 = Language("Python")
val list = arrayListOf<Language>()
list.add(language1)
list.add(language2)
list.add(language3)
list.add(language4)
val user = User("MuFeng", list)
//map操作符實現
Observable.just(user)
.map { user.languages }
.subscribeBy {
for (l in it) {
Log.e("TAG", l.name)
}
}
Log.e("TAG", "----------------------------------")
//flatMap操作符實現
Observable.just(user)
.flatMap { user.languages.toObservable() }
.subscribeBy {
Log.e("TAG", it.name)
}
}
複製程式碼
執行結果
09-07 11:27:53.354 12548-12548/com.mufeng.rxjavademo E/TAG: Android
Java
Kotlin
Python
09-07 11:27:53.355 12548-12548/com.mufeng.rxjavademo E/TAG: ----------------------------------
09-07 11:27:53.357 12548-12548/com.mufeng.rxjavademo E/TAG: Android
Java
Kotlin
Python
複製程式碼
我們發現執行的結果是一樣的
flatMap對這些Observable發射的資料做的是合併操作,因此flatMap操作後的資料序列是無序的.如果要嚴格按照順序發射這些資料請使用concatMap操作符
三. GroupBy
groupBy操作符將一個Observable拆分為一些Observables集合,它們中的每一個都發射原始Observable的一個子序列
實際應用:
場景: 我們給出0-50把他們分成兩組: 奇陣列和偶陣列,並列印出所有的偶數
- 我們先把0-50分成兩組: 奇陣列合偶陣列
fun testGroupBy(){
Observable.range(0,51)
.groupBy {
if (it % 2 == 0)
"偶陣列"
else
"奇陣列"
}
.subscribe {
//列印分組名稱
Log.e("TAG","GroupName: ${it.key}")
//列印出所有偶數
if (it.key == "偶陣列") {
it.subscribeBy { Log.e("TAG","偶數: $it") }
}
}
}
複製程式碼
執行結果
09-07 06:09:36.984 1730-1730/com.mufeng.rxjavademo E/TAG: GroupName: 偶陣列
偶數: 0
GroupName: 奇陣列
偶數: 2
偶數: 4
偶數: 6
偶數: 8
09-07 06:09:36.985 1730-1730/com.mufeng.rxjavademo E/TAG: 偶數: 10
偶數: 12
偶數: 14
偶數: 16
偶數: 18
偶數: 20
偶數: 22
偶數: 24
偶數: 26
偶數: 28
09-07 06:09:36.986 1730-1730/com.mufeng.rxjavademo E/TAG: 偶數: 30
偶數: 32
偶數: 34
偶數: 36
偶數: 38
偶數: 40
偶數: 42
偶數: 44
偶數: 46
偶數: 48
09-07 06:09:36.988 1730-1730/com.mufeng.rxjavademo E/TAG: 偶數: 50
複製程式碼
四. Buffer
buffer 會定期收集Observable資料並放進一個資料包裹,然後發射這些資料包裹,而不是一次發射一個值
buffer 操作符將一個Observable變換成另一個,原來的Observable正常發射資料,由變換產生的Observable發射這些資料的快取集合
fun testBuffer(){
Observable.range(1,10)
.buffer(2)
.subscribeBy(
onNext = {Log.e("TAG",it.toString())},
onComplete = {Log.e("TAG","onComplete")}
)
}
複製程式碼
執行結果
09-07 06:20:14.557 1996-1996/com.mufeng.rxjavademo E/TAG: [1, 2]
[3, 4]
[5, 6]
09-07 06:20:14.558 1996-1996/com.mufeng.rxjavademo E/TAG: [7, 8]
[9, 10]
onComplete
複製程式碼
buffer還有許多過載方法,比較常用的buffer(count,skip):
buffer(count,skip)從原始Observable的第一項資料開始建立新的快取,此後每當收到skip項資料,就用count項資料填充快取;開頭的一項和後續的count-1項.它以列表List的形式發射快取,這些快取可能會有重疊的部分(當skip < count時),也可能會有間隙(當skip>count時),主要取決於count和skip的值
fun testBuffer(){
Observable.range(1,10)
.buffer(5,1)
.subscribeBy(
onNext = {Log.e("TAG",it.toString())},
onComplete = {Log.e("TAG","onComplete")}
)
}
複製程式碼
執行結果
09-07 06:30:03.621 1996-1996/com.mufeng.rxjavademo E/TAG: [1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
[3, 4, 5, 6, 7]
[4, 5, 6, 7, 8]
[5, 6, 7, 8, 9]
[6, 7, 8, 9, 10]
09-07 06:30:03.622 1996-1996/com.mufeng.rxjavademo E/TAG: [7, 8, 9, 10]
[8, 9, 10]
[9, 10]
[10]
onComplete
複製程式碼
注意: 如果原來的Observable發射了一個onError通知,那麼buffer 會立即傳遞這個通知,而不是首先發射快取的資料,即使在這之前快取中包含了原始Observable發射的資料
五. Window
定期將來自原始Observable的資料分解為一個Observable視窗,發射這些視窗,而不是每次發射一項資料
fun testWindow(){
Observable.range(1,10)
.window(2)
.subscribeBy(
onNext = {
Log.e("TAG","onNext: ")
it.subscribeBy { Log.e("TAG","onNext: $it") }
},
onComplete = {Log.e("TAG","onComplete")}
)
}
複製程式碼
執行結果
09-07 14:47:47.381 26617-26617/com.mufeng.rxjavademo E/TAG: onNext:
09-07 14:47:47.382 26617-26617/com.mufeng.rxjavademo E/TAG: onNext: 1
onNext: 2
onNext:
onNext: 3
onNext: 4
onNext:
09-07 14:47:47.383 26617-26617/com.mufeng.rxjavademo E/TAG: onNext: 5
onNext: 6
onNext:
onNext: 7
onNext: 8
onNext:
onNext: 9
09-07 14:47:47.384 26617-26617/com.mufeng.rxjavademo E/TAG: onNext: 10
onComplete
複製程式碼
以上都是常用的變換操作符,下一篇回顧一下RxJava過濾操作符