前言
Channel是是热流。每次发送只有一个地方接收数据,写生产者和消费者模型很方便。Flow是冷流,可以有多个地方接收(多个消费者消费同一个数据)。ShareFlow和StateFow是协程的热流实现,对应RxJava中PublishSubject和BehaviorSubject.
热流可以比作超市,冷流可以比作生产线。
- 在java中RxJava可以处理复杂频繁的数据,比LiveData有优势
- 在协程中Flow可以处理复杂频繁的数据,比LiveData有优势
- Flow与生命周期无绑定(可以借助Lifecycle状态实现),LiveData有生命周期。
- Flow简化了Api,相对于RxJava简单。
Flow有替代LiveData和RxJava的趋势。Flow的局限在于只能在协程中使用
replay粘性事件的个数,不同消费者订阅后,重新接收replay个之前的数据。
fun main() {
runBlocking {
val flow = MutableSharedFlow<String>(replay = 1)
// 第一个订阅
launch {
flow.collect{
println("collect1:$it")
}
}
// 生产数据
launch {
(1..4).forEach{
println("emit:$it")
flow.emit("$it")
}
}
//第二个订阅者 模拟在生产数据后才订阅
launch {
delay(1000)
flow.collect{
println("collect2:$it")
}
}
}
}
}
输出:
emit:1
emit:2
collect1:1
collect1:2
emit:3
emit:4
collect1:3
collect1:4
collect2:4
replay=n时,多次订阅会将生产者的最后n次事件重新发送一遍。
extraBufferCapacity
额外的缓存池。总的缓冲池extraBufferCapacity+replay个,用于生产速率>消费速率的情况。
fun main() {
runBlocking {
val flow = MutableSharedFlow<String>(replay = 2, extraBufferCapacity = 1)
// 第一个订阅
launch {
flow.collect{
delay(2000)
println("collect1:$it")
}
}
// 生产数据
launch {
(1..10).forEach{
flow.emit("$it")
println("emit:$it")
delay(100)
}
}
}
}
输出:
emit:1
emit:2
emit:3
emit:4
collect1:1
emit:5
collect1:2
emit:6
collect1:3
emit:7
collect1:4
emit:8
collect1:5
emit:9
collect1:6
emit:10
collect1:7
collect1:8
collect1:9
collect1:10
当缓存池满后,消费掉一个才会生产一个,生产者挂起。extraBufferCapacity=1时,发送和接收交替打印。当extraBufferCapacity>=7时,发送日志打印完毕后才开始打印接收日志。
onBufferOverFlow
缓冲策略,和Java线程池类似。线程池的拒绝策略。
public enum class BufferOverflow {
//默认的,当生产速率大于消费速率并且缓冲池已满的情况,会挂起生产者,等待消费者
SUSPEND,
//丢弃老的数据
DROP_OLDEST,
//丢弃新的数据
DROP_LATEST
}
StateFlow
StateFlow是一种特殊的ShareFlow。replay=1。必须要有初始值,不能为空,两次数据一致的情况下不会触发第二次。 LiveData相同点: 1、允许多个消费者订阅 2、粘性事件,事件数量=1 3、产生数据太快时都会丢失数据
StateFlow模式是BufferOverflow.DROP_OLDEST。Sharedflow是BufferOverflow.SUSPEND
不同点:
- StateFlow必须有默认值
- 默认是防抖,LiveData不防抖
- StateFlow没有和生命周期绑定
LiveData防抖可使用distinctUntilChanged。StateFlow没有生命周期绑定,可以利用Liecycle,在协程作用域内使用repeatOnLifecycle.
总结
ShareFlow丢弃订阅之前发送内存(replay默认0)
- StateFlow是特殊的ShareFlow,replay=1 onBufferOverflow=BufferOverFlow.SUSPEND emit方法永远不会挂起。忽略两次重复的值
- StateFlow可以替代LiveData使用
- StateFlow必须有默认值,默认防抖,有粘性事件,没有生命周期绑定。重复发射和收集同样的值。
- ShareFlow没有默认值,粘性事件,可自定义事件数量,有缓冲池
- StateFlow表示状态,如View的显示和隐藏,按钮selectd都需要默认值
- ShareFlow是存储数据,例如列表
list<T>数据,屏幕发生旋转,在Fragment的view消耗重建后的数据恢复 - 数据列表用
ShareFlow<List<data>>,点赞或收藏数据的变化用StateFlow