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能有效减少数据库查询次数,提升性能。
相关推荐
芦半山1 天前
快速应用「幽灵调用」的正式修复
android·gradle
向阳花开_miemie1 天前
Android音频学习(二十)——高通HAL
android·学习·音视频
2501_925317131 天前
博客SEO优化实战:从Google到百度,一套可复制的排名增长SOP
android·百度·rxjava
Charles豪1 天前
MR、AR、VR:技术浪潮下安卓应用的未来走向
android·java·人工智能·xr·mr
2501_915921431 天前
HTTPS 映射如何做?(HTTPS 映射配置、SNI 映射、TLS 终止、内网映射与 iOS 真机验证实战)
android·网络协议·ios·小程序·https·uni-app·iphone
TeleostNaCl1 天前
SMBJ 简单使用指南 实现在 Java/Android 程序中访问 SMB 服务器
android·java·运维·服务器·经验分享·kotlin
小孔龙1 天前
Kotlin 序列化:重复引用是技术问题还是架构缺陷?
android·kotlin·json
掘金一周1 天前
2025年还有前端不会Nodejs ?| 掘金一周 9.25
android·前端·后端
2501_915106321 天前
iOS 混淆与机器学习模型保护 在移动端保密权重与推理逻辑的实战指南(iOS 混淆、模型加密、ipa 加固)
android·人工智能·机器学习·ios·小程序·uni-app·iphone
低调小一1 天前
从Android到iOS:启动监控实现的跨平台技术对比
android·ios·cocoa