Kotlin协程-ShareFlow

前言

replay粘性事件的个数,不同消费者订阅后,重新接收replay个之前的数据。

kotlin 复制代码
    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次事件冲i性能发送一遍。

extraBufferCapacity

额外的缓存池。总的缓冲池extraBufferCapacity+replay个,用于生产速率>消费速率的情况。

kotlin 复制代码
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线程池类似。线程池的拒绝策略。

kotlin 复制代码
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

不同点:

  1. StateFlow必须有默认值
  2. 默认是防抖,LiveData不防抖
  3. StateFlow没有和生命周期绑定

LiveData防抖可使用distinctUntilChanged。StateFlow没有生命周期绑定,可以利用Liecycle,在协程作用域内使用repeatOnLifecycle.

总结

  1. StateFlow是特殊的ShareFlow,replay=1 onBufferOverflow=BufferOverFlow.SUSPEND
  2. StateFlow可以替代LiveData使用
  3. StateFlow必须有默认值,默认防抖,有粘性事件,没有生命周期绑定
  4. ShareFlow没有默认值,粘性事件,可自定义事件数量,有缓冲池
  5. StateFlow表示状态,如View的显示和隐藏,按钮selectd都需要默认值
  6. ShareFlow是存储数据,例如列表list<T>数据,屏幕发生旋转,在Fragment的view消耗重建后的数据恢复
  7. 数据列表用ShareFlow<List<data>>,点赞或收藏数据的变化用StateFlow
相关推荐
千码君201610 小时前
kotlin:Jetpack Compose 给APP添加声音(点击音效/背景音乐)
android·开发语言·kotlin·音效·jetpack compose
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.10 小时前
MySQL半同步复制与GTID实战详解
android·mysql·adb
用户416596736935511 小时前
深度解码:记一次视频时间戳(PTS)异常导致的播放故障排查
android
大白菜和MySQL13 小时前
linux系统环境常用命令
android·linux·adb
Ehtan_Zheng13 小时前
彻底告别 AndroidX 依赖:如何在 KMP 中构建 100% 复用的 UI 逻辑层?
android
Hello小赵13 小时前
C语言如何自定义链接库——编译与调用
android·java·c语言
IT枫斗者14 小时前
构建具有执行功能的 AI Agent:基于工作记忆的任务规划与元认知监控架构
android·前端·vue.js·spring boot·后端·架构
用户693717500138415 小时前
XChat 为什么选择 Rust 语言开发
android·前端·ios
林栩link15 小时前
【车载 Android】实践跨进程 UI 融合渲染
android
Paxon Zhang15 小时前
MySQL 大师之路**数据库约束,表设计,CRUD**
android·数据库·mysql