Android Flow的其他使用:stateIn和冷流(普通Flow)

一、数据库使用冷流(普通Flow)和热流(stateIn转换)的区别

scss 复制代码
val lightFlow = DataBase.getInstance()
    .getLightDao()
    .getData()
    .flowOn(Dispatchers.IO) // 在 IO 线程执行查询
ini 复制代码
val lightHistoryFlow = DataBase.getInstance().getLightDao().queryLimitCountF(50).map {
    if (it.isEmpty()) {
        LightData.fakeData(
            listOf(
                LightEntity(value =400f, time = Date()),
                 LightEntity(value =500f, time = Date()),
            )
        )
    } 
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5000),
    initialValue = LightData.fakeData(emptyList())
)

1.1 两段代码的核心区别

特性 lightFlow(普通 Flow) lightHistoryFlow(StateFlow)
流类型 冷流(Flow 热流(通过stateIn转换为StateFlow
状态持有 不持有状态,无初始值 持有状态,有initialValue
订阅行为 每次collect都会触发数据源重新执行(如数据库查询) 多次collect共享同一数据流,数据源只执行一次
新订阅者 重新执行上游逻辑(重新查数据库) 立即收到当前持有的状态值,不会重新执行上游
生命周期 与订阅者绑定,无订阅时上游逻辑停止 与指定的scope绑定,在started条件满足时保持活跃

lightFlow(普通冷流)

  • 每次调用collect时,都会重新执行getData()对应的数据库查询
  • 没有 "当前值" 的概念,订阅者只能获取订阅之后产生的新数据
  • 当所有订阅者取消订阅后,上游的数据库查询会停止(冷流特性)

执行流程:

复制代码
订阅1 → 触发数据库查询 → 发射结果
订阅2 → 再次触发数据库查询 → 发射结果
所有订阅取消 → 数据库查询停止

lightHistoryFlow(热流 StateFlow)

  • 通过stateIn将冷流转换为热流,数据库查询queryLimitCountF(50)只会执行一次
  • 结果会被缓存为 "状态",新订阅者立即收到当前缓存的状态(initialValue或最新结果)
  • viewModelScopeSharingStarted.WhileSubscribed(5000)控制生命周期:当有活跃订阅时保持数据更新,无订阅 5 秒后停止上游,节省资源

执行流程:

复制代码
首次订阅 → 触发数据库查询 → 结果缓存为状态 → 所有订阅者共享该状态
新订阅者加入 → 直接获取当前缓存状态(不查数据库)
无订阅5秒后 → 停止上游,但保留最后状态
再次订阅 → 立即返回保留的状态,同时重新启动上游更新

1.2具体建议

在你的健康数据场景中:

  • 如果lightFlow是 "获取最新光照
    建议改为StateFlow,避免重复查询数据库:
ini 复制代码
val LightFlow = DataBase.getInstance()
    .getLightDao()
    .getData()
    .flowOn(Dispatchers.IO) // 在 IO 线程执行查询
    .stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = null // 适合的初始值
    )
  • lightHistoryFlow的写法是合理的
    历史记录数据适合作为 "状态" 缓存,且可能被多个 UI 组件订阅,stateIn能有效减少数据库查询次数,提升性能。
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
ai2work2 天前
ch23 综合复刻:从零做一个最小可用版本(capstone)
kotlin
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
ai2work2 天前
ch21 签名、校验与发版
kotlin
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui