【Android】Flow基础知识和使用

【Android】Flow学习及使用

在Android开发中,Flow是Kotlin协程库提供的一个核心组件,用于处理异步数据流。它是一种冷流(cold stream),意味着数据生产仅在有收集者(collector)调用collect时开始,并按顺序发射多个值。‌

基本概念与核心特点

  • 冷流特性‌:Flow是冷的,只有当调用collect方法时才会启动数据生产流程。每个收集者都会触发完整的数据流从头开始。‌

  • 异步多值发射‌:通过flow构建器定义数据源,使用emit函数发射值,支持挂起函数(如delay)实现非阻塞异步操作。‌

  • 操作符链式调用‌:支持中间操作符(如map、filter)对数据流进行转换和过滤,末端操作符(如collect)启动收集流程。‌

基础用法示例

bash 复制代码
// 定义一个Flow,异步发射数字1、2、3,间隔1秒
val numbersFlow = flow {
    for (i in 1..3) {
        delay(1000)
        emit(i)
    }
}

// 在Android中收集数据(例如在ViewModel中)
lifecycleScope.launch {
    numbersFlow.collect { value ->
        Log.d("Flow", "收到: $value")
    }
}

运行结果会按顺序输出1、2、3,每项间隔1秒。‌

与LiveData的对比

  • Flow优势‌:支持挂起函数、丰富的操作符链式调用(如防抖、去重)、更灵活的错误处理。适用于复杂异步场景(如网络请求、实时搜索)。‌

  • LiveData适用场景‌:轻量级数据绑定,简单生命周期感知更新。但不支持挂起函数,链式操作能力较弱。‌

  • 选择建议‌:若需复杂流式处理(如实时搜索、连续网络请求),Flow更合适;若仅需简单UI数据绑定,LiveData可能更轻量。‌

高级特性与热流对比

‌冷流 vs 热流‌:

  • 冷流(如Flow)‌:每个收集者独立接收完整数据流,适用于网络请求、数据库查询等场景。‌

  • 热流(如StateFlow、SharedFlow)‌:数据生产独立于收集者,多个收集者共享同一数据源,适用于实时广播、状态共享。‌

  • 错误处理‌:可通过catch操作符捕获异常,避免流中断。‌

热流StateFlow、SharedFlow

常见的热流有StateFlow和SharedFlow。(LiveData也是一个热流)

知道了冷流是只有接收者接受数据时,发送者才会去产生数据再发送数据给接收者。并且每个接收者都会触发完整的数据流从头开始接收完整的数据源。

而热流就是不管有没有接受者来接收数据,发送者都会生产数据,多个接受者时共享同一份数据源的,同时接受者并不会接收完整的数据源,发送者数据生产到哪了接受者就接收到哪的数据。

说的通俗一点就是:

  • 冷流就像刷视频,我们开始刷这个视频这个视频才会开始播放,并且是从头开始播放
  • 热流就像直播,我们不看直播这个直播也在播放,点进直播间观看也并不是从头开始看,而是只能从当前的内容开始看

冷流Demo:

bash 复制代码
//每次collect都会重新发射数据 
val coldFlow = flow { 
    println("开始生产数据")
    emit(1) 
    emit(2) 
} 

// 观察者1
coldFlow.collect { println("观察者1: $it") } // 输出:1,2 
// 观察者2
coldFlow.collect { println("观察者2: $it") } // 再次输出:1,2

适用场景:

  • 网络请求、数据库查询等需要独立数据源的场景
  • 每个订阅者需要从头消费完整的数据

热流Demo:

bash 复制代码
// 创建热流(SharedFlow) 
val hotFlow = MutableSharedFlow<Int>()

// 启动协程持续发射数据(即使没有订阅者)
CoroutineScope(Dispatchers.Default).launch { 
    repeat(4) { 
        delay(1000) 
         // 发射 0 1 2 3 4
        hotFlow.emit(it)
    } 
}

// 观察者1(延迟1秒订阅) 
CoroutineScope(Dispatchers.Main).launch {
    delay(1000) 
    hotFlow.collect { println("观察者1: $it") } // 只能收到 1,2,3,4
} 

// 观察者2(延迟5秒订阅) 
CoroutineScope(Dispatchers.Main).launch { 
    delay(5000) 
    hotFlow.collect { println("观察者2: $it") } // 收不到任何数据(发射已结束) 
}

适用场景:

  • 需要共享实时数据的场景(如IM消息、用户定位更新)
  • 数据生产是连续且独立的

总结:

冷流(Flow、asFlow) 热流(StateFlow、SharedFlow)
数据产生发送时机 接受者收集数据时(collect) 直接产生数据,不管有没有接受者收集
数据独立性 每个接受者收到的数据时独立的 所有接受者共享数据
数据历史 每个接受者从头开始获取完整数据 只能获取订阅后产生的数据

典型应用场景

  • 网络请求‌:在ViewModel中返回Flow,Activity/Fragment中收集响应数据。‌

  • UI状态管理‌:结合Jetpack组件(如Flow Paging)处理分页数据或复杂导航状态。‌

  • 实时功能‌:如搜索输入流,通过debounce操作符实现防抖。‌

注意事项

  • 生命周期管理‌:在Android中需配合lifecycleScope或viewModelScope确保协程生命周期与UI一致。‌
  • 性能优化‌:避免在Flow中执行阻塞操作,使用flowOn指定调度器(如Dispatchers.IO)。‌
相关推荐
李新_3 小时前
基于Markwon封装Markdown组件
android·aigc·markdown
Non-existent9875 小时前
Flutter + FastAPI 30天速成计划自用并实践-第10天-组件化开发实践
android·flutter·fastapi
@老蝴7 小时前
MySQL数据库 - 约束和联合查询
android·数据库·mysql
ljt27249606618 小时前
Compose笔记(六十一)--SelectionContainer
android·笔记·android jetpack
有位神秘人8 小时前
Android中Compose系列之按钮Button
android
AI科技摆渡9 小时前
GPT-5.2介绍+ 三步对接教程
android·java·gpt
csdn12259873369 小时前
Android12 新启动页到底该怎么做
android·启动页
aaajj10 小时前
【Android】关于MY_PACKAGE_REPLACED广播
android
4Forsee11 小时前
【Android】动态操作 Window 的背后机制
android·java·前端