【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)。‌
相关推荐
莞凰1 天前
昇腾CANN的“灵脉根基“:Runtime仓库探秘
android·人工智能·transformer
NiceCloud喜云1 天前
Claude Files API 深入:从上传、复用到配额管理的工程化指南
android·java·数据库·人工智能·python·json·飞书
ujainu1 天前
CANN pto-isa:虚拟指令集如何连接编译与执行
android·ascend
赏金术士1 天前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
TechMerger1 天前
Android 17 重磅重构!服役 20 年的 MessageQueue 迎来无锁改造,卡顿大幅优化!
android·性能优化
yuhuofei20211 天前
【Python入门】Python中字符串相关拓展
android·java·python
dalancon1 天前
Android Input Spy Window
android
dalancon1 天前
InputDispatcher派发事件,查找目标窗口
android
我命由我123451 天前
Android Framework P3 - MediaServer 进程、认识 ServiceManager 进程
android·c语言·开发语言·c++·visualstudio·visual studio·android runtime
天才少年曾牛1 天前
Android14 新增系统服务后,应用调用出现 “hidden api” 警告的原因与解决方案
android·frameworks