RxJava 學習筆記 -- 變換操作符

小碼農沐楓發表於2018-09-08

RxJava 基礎知識

image

RxJava 學習筆記 -- 變換操作符

image

操作符作用
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發射的每一項資料應用一個函式,執行變換操作

image

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

image

實際應用:
場景: 列印使用者的所掌握的開發語言

  1. 我們需要先建立一個使用者的資料類
data class User(var name: String, var languages: ArrayList<Language>)

data class Language(var name: String)
複製程式碼
  1. 我們分別用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的一個子序列

image

實際應用:
場景: 我們給出0-50把他們分成兩組: 奇陣列和偶陣列,並列印出所有的偶數

  1. 我們先把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發射這些資料的快取集合

image

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視窗,發射這些視窗,而不是每次發射一項資料

image

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過濾操作符


相關文章