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能有效减少数据库查询次数,提升性能。
相关推荐
RainyJiang6 小时前
谱写Kotlin协程面试进行曲-进阶篇(第二乐章)
面试·kotlin·android jetpack
mygljx9 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
xinhuanjieyi10 小时前
ruoyimate导入sql\antflow\bpm_init_db.sql报错
android·数据库·sql
闲猫11 小时前
基于RABC的权限控制设计
android
星霜笔记14 小时前
GitMob — 手机端 GitHub 管理工具
android·kotlin·github·android jetpack
LiuYaoheng15 小时前
问题记录:Android Studio Low memory
android·ide·android studio
独隅16 小时前
Python 标准库 (Standard Library) 全面使用指南
android·开发语言·python
always_TT16 小时前
strlen、strcpy、strcat等常用字符串函数
android
qqty121716 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
2401_8955213416 小时前
MySQL中between and的基本用法
android·数据库·mysql