【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)。‌
相关推荐
xiangpanf5 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx8 小时前
安卓线程相关
android
消失的旧时光-19439 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon10 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon10 小时前
VSYNC 信号完整流程2
android
dalancon10 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户693717500138411 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android11 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才12 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶13 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle