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过滤操作符