Kotin的Flow, 就是Java的RxJava框架, 但是使用更加简洁。 结合协程的作用域,协程被取消时,Flow也会被取消,也能避免内存泄漏。
1. 引入库
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation "androidx.activity:activity-ktx:1.6.1"
implementation "androidx.fragment:fragment-ktx:1.5.5"
implementation 'androidx.core:core-ktx:1.9.0'
前两项是协程库,因为Flow是构建在Kotlin协程基础之上的。第三项是用来提供协程作用域的。
后两项是ktx的扩展库,能帮我们简化不少代码的书写。最后一项是系统扩展的。
2. 普通操作符
掌握这些操作符基本够用了。
- map
转换上流的数据,处理后,再向下发送给接收者。
- filter
根据设定的条件,过滤掉上流的数据。
- onEach
遍历每一条数据。通常用在调试查看中间状态值的。 上流初始数据,很可能在中流就被转换过了。用onEach就可以查看。
- debounce
使得上流各项数据之间存在一定的时间间隔,不在时间间隔内就会删除上流过来的数据,不再下发给下流监听者。 时间点过于临近的数据只会保留最后一条。
- sample
sample是采样的意思,在规定时间内读取上流的数据。当上流数据来的很快很频繁, 就是下流并不需要这么数据,只需展示少量数据的时候比较有用。
- reduce
累积上流的数据。它是一个终端操作符,就是和collect一样,是下流监听者。
flow.reduce { acc, value -> acc + value }
- fold
和reduce操作符类似,也是一个终端操作符。区别在于,fold需要传入一个初始值,这个初始值会作为首个累积值被传递到fold的函数体当中,它的公式如下:
flow.fold(initial) { acc, value -> acc + value }
3.合并操作符
- flatMapConcat
flatMap有三个操作符。它们是用来转换上流的。和map不同的地方是, map是转换上流的数据,而 flatMap是把上流给转换了。把老的flow换成了新的flow, 数据和数据类型肯定也变了。
flatMapConcat就是典型的。flatMapConcat能保证上流数据的顺序,相当于单线程处理数据, 上流发一个,flatMapConcat处理一个。
- flatMapMerge
和flatMapConcat不同,flatMapConcat能保证上流数据的顺序,相当于单线程处理数据。但是flatMapMerge的内部是启用多线程并发来进行数据处理的,它不会保证最终结果的顺序。
- flatMapLatest
flow1中的数据传递到flow2中会立刻进行处理,但如果flow1中的下一个数据要发送了,而flow2中上一个数据还没处理完,则会直接将剩余逻辑取消掉,开始处理最新的数据。
- zip
也就是多个上流flow,合并成一个上流flow。而且多个上流flow,它们之间是并行运行的。同时发出。当个数一样的时候,等少了上流flow发完时,就结束了。其他上流flow的数据就舍弃了。
4.背压操作符
如果上流的流速大于下流处理数据的速度,并且不均匀问题持续放大。这就是背压问题。下面是处理背压的操作符。
- buffer
buffer操作符可以释放上流产能。
collect函数中的数据处理是会对flow函数中的数据发送产生影响的。因为默认情况下,collect函数和flow函数会运行在同一个协程当中,因此collect函数中的代码没有执行完,flow函数中的代码也会被挂起等待。
也就是说,我们在collect函数中处理数据需要花费1秒,flow函数同样就要等待1秒。collect函数处理完成数据之后,flow函数恢复运行
那能不能,上流发上流的, 下流处理下流的,各自独立呢? 也行的,就是用buffer操作符。 上流发过来的数据先存在buffer中, 下流有时间处理的时候就去拿。
- collectLatest
当有新数据到来时而前一个数据还没有处理完,则会将collectLastest中前一个数据剩余的处理逻辑全部取消。马上去处理新的数据。很喜新厌旧。
- conflate
和collectLastest不同, conflate会保持collect中的处理逻辑完整性。
5. StateFlow和SharedFlow
StateFlow和SharedFlow可以替换LiveData。StateFlow具有粘性,SharedFlow默认不具有粘性,当也可以变成有粘性。使用flow构建函数构建出的Flow是属于冷流,也就是在没有任何接受端的情况下,Flow是不会工作的
我们知道Flow的特点之一就是冷流。当数据被订阅的时候,发布者才开始执行发射数据流的代码。并且当有多个订阅者的时候,每一个订阅者和发布者都是一对一的关系,每个订阅者都会收到发布者完整的数据。
引用: