Kotlin Flow 完全指南

Kotlin Flow 完全指南

一、Flow 到底是什么

一句话:Flow = Kotlin 的"异步数据流"

它是:协程版 RxJava

但:

  • 更轻量
  • 更简单
  • 更符合 Kotlin 风格

你可以把 Flow 理解成:"会持续发数据的管道"

比如:

  • 网络请求状态
  • 输入框搜索
  • 倒计时
  • WebSocket
  • 数据库变化
  • 页面状态更新

这些都不是:只返回一次 ,而是:持续产生数据

这就是:Flow 的核心


二、先用最容易理解的例子

普通函数

kotlin 复制代码
fun getData(): String {
    return "hello"
}

只能返回一次:hello → 结束

Flow

kotlin 复制代码
fun getFlow() = flow {
    emit("hello")
    delay(1000)
    emit("world")
}

它会:hello → 1秒后 → world

也就是:可以连续发送数据


三、最核心的两个东西

Flow 只有两个关键点:

方法 作用
emit() 发送数据
collect() 接收数据
kotlin 复制代码
flow.collect { }

四、第一个完整 Flow

创建

kotlin 复制代码
val flow = flow {
    emit(1)
    emit(2)
    emit(3)
}

收集

kotlin 复制代码
lifecycleScope.launch {
    flow.collect {
        println(it)
    }
}

输出:

复制代码
1
2
3

五、为什么必须在协程里 collect

因为:Flow 是挂起的

collect 本质是 suspend fun collect()

所以必须:launch 或在 suspend 函数里调用。


六、Flow 执行流程(超重要)

很多人学不会就是这里没懂。

Flow 是"冷流" ------ 你不 collect,它就不执行。

kotlin 复制代码
val flow = flow {
    println("开始")
    emit(1)
}

此时:什么都不会打印,因为没人收集。

collect 后:

kotlin 复制代码
flow.collect()

才会输出:开始1


七、最经典 Android 场景

场景1:网络请求状态

这是实际项目最多的。

不使用 Flow

kotlin 复制代码
fun login(callback: Callback)

回调地狱。

Flow 版本

kotlin 复制代码
fun login() = flow {
    emit(Loading)
    val result = api.login()
    emit(Success(result))
}

页面:

kotlin 复制代码
lifecycleScope.launch {
    viewModel.login().collect {
        when(it) {
            is Loading -> showLoading()
            is Success -> showData()
        }
    }
}

这就是:MVVM + Flow,现代 Android 标配。


八、StateFlow(真正项目核心)

实际项目用最多的不是 Flow,而是:StateFlow

因为 UI 需要:

  • 始终持有最新状态

九、StateFlow 最容易理解方式

它像:LiveData 升级版

但:

  • 协程化
  • 更强
  • 更快
  • 支持 Flow 全家桶

十、最经典 StateFlow

ViewModel

kotlin 复制代码
class MainViewModel : ViewModel() {

    private val _state = MutableStateFlow("默认值")
    val state = _state.asStateFlow()

    fun update() {
        _state.value = "新数据"
    }
}

页面监听

kotlin 复制代码
lifecycleScope.launch {
    viewModel.state.collect {
        tv.text = it
    }
}

StateFlow 最大特点:永远有值

kotlin 复制代码
MutableStateFlow("默认值")

必须给初始值,因为它代表:当前状态


十一、为什么 Google 推荐 StateFlow 替代 LiveData

特性 StateFlow LiveData
协程支持
操作符 超多 很少
Kotlin 化 完全 一般
冷热流支持 支持 不支持
性能 更强 一般
官方趋势 主推 逐渐弱化

十二、实际项目最常见结构:UIState

现代 Android 必会。

定义状态

kotlin 复制代码
sealed class UIState {
    object Loading : UIState()
    data class Success(val data: String) : UIState()
    data class Error(val msg: String) : UIState()
}

ViewModel

kotlin 复制代码
private val _uiState = MutableStateFlow<UIState>(UIState.Loading)
val uiState = _uiState.asStateFlow()

// 更新状态
viewModelScope.launch {
    try {
        val result = api.getData()
        _uiState.value = UIState.Success(result)
    } catch (e: Exception) {
        _uiState.value = UIState.Error("失败")
    }
}

页面

kotlin 复制代码
lifecycleScope.launch {
    viewModel.uiState.collect {
        when(it) {
            is UIState.Loading -> { /* show loading */ }
            is UIState.Success -> { /* show data */ }
            is UIState.Error -> { /* show error */ }
        }
    }
}

十三、SharedFlow 是什么

一句话:可广播事件流

  • StateFlow:保存状态
  • SharedFlow:发送事件

十四、最经典场景:Toast

Toast:一次性事件,不应该保存状态。

SharedFlow

kotlin 复制代码
private val _event = MutableSharedFlow<String>()
val event = _event

// 发送
_event.emit("登录成功")

// 页面
collect {
    Toast.makeText(context, it, Toast.LENGTH_SHORT).show()
}

十五、为什么 Toast 不能用 StateFlow

因为 StateFlow 会记住最后一个值。

旋转屏幕后:Toast 又弹一次

这就是经典的 LiveData Event 问题,SharedFlow 可以避免。


十六、Flow 最重要操作符

map --- 数据转换

kotlin 复制代码
flow.map { it * 2 }

filter --- 过滤

kotlin 复制代码
flow.filter { it > 10 }

debounce(Android 超常用)--- 防抖

搜索框神器:

kotlin 复制代码
editTextFlow.debounce(500)
// 停止输入500ms后才搜索

十七、搜索框实战(面试高频)

kotlin 复制代码
editTextFlow
    .debounce(500)
    .distinctUntilChanged()
    .collect { search(it) }
操作符 含义
debounce 停止输入再搜索,避免疯狂请求
distinctUntilChanged 内容没变不重复搜索

十八、flatMapLatest(巨重要)

这是:Flow 灵魂操作符

场景 :用户快速搜索 aababcabcd,你希望只保留最后一次请求。

kotlin 复制代码
queryFlow.flatMapLatest { repository.search(it) }

效果:

  • 旧请求:自动取消
  • 只保留:最新请求

十九、Android 搜索框完整实战

kotlin 复制代码
searchFlow
    .debounce(300)
    .distinctUntilChanged()
    .flatMapLatest { repository.search(it) }
    .flowOn(Dispatchers.IO)
    .collect { adapter.submitList(it) }

二十、flowOn 是什么

切线程:

kotlin 复制代码
flow {
    emit(api.getData())
}.flowOn(Dispatchers.IO)

表示:上游在 IO 线程

collect 默认在当前协程线程,通常是 Main


二十一、catch 异常处理

kotlin 复制代码
flow {
    emit(api.getData())
}.catch {
    emit(emptyList())
}

二十二、onStart --- 开始加载

kotlin 复制代码
flow.onStart { showLoading() }

二十三、onCompletion --- 结束

kotlin 复制代码
flow.onCompletion { hideLoading() }

二十四、Room 为什么天然支持 Flow

kotlin 复制代码
@Query("SELECT * FROM users")
fun getUsers(): Flow<List<User>>

数据库变化:自动通知 UI

这是:响应式数据库


二十五、Compose 为什么和 Flow 天生搭配

  • Compose:状态驱动 UI
  • Flow:状态流

天然适配:

kotlin 复制代码
val state by viewModel.state.collectAsState()

UI 自动刷新。


二十六、Flow vs LiveData

对比 Flow LiveData
协程支持
操作符 超多 很少
Kotlin 化 完全 一般
冷热流支持 支持 不支持
性能 更强 一般
官方趋势 主推 逐渐弱化

二十七、Flow vs RxJava

对比 Flow RxJava
学习成本
Kotlin 支持 官方 一般
操作符数量 中等 超多
Android 官方 主推 非主推
协程融合 原生 不自然

二十八、项目里真正怎么用

现代 Android 通常:

  1. Repository 返回 Flow:fun getData(): Flow<Data>
  2. ViewModel 转 StateFlow:MutableStateFlow
  3. UI collect
  4. repeatOnLifecycle

二十九、repeatOnLifecycle(非常重要)

错误写法

kotlin 复制代码
launch {
    flow.collect {}
}

页面退出可能还在收集。

正确写法

kotlin 复制代码
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        flow.collect { }
    }
}
  • 页面不可见:自动停止
  • 页面回来:自动恢复

三十、Android 项目最佳实践结构

Repository

kotlin 复制代码
fun getUser() = flow {
    emit(api.getUser())
}

ViewModel

kotlin 复制代码
val uiState = repository.getUser()
    .stateIn(
        viewModelScope,
        SharingStarted.WhileSubscribed(),
        UIState.Loading
    )

Activity/Fragment

kotlin 复制代码
repeatOnLifecycle(Lifecycle.State.STARTED) {
    viewModel.uiState.collect { }
}

三十一、最容易记忆的一张图

复制代码
Flow
├── 数据流
├── emit → 发数据
└── collect → 收数据

StateFlow → 保存状态
SharedFlow → 发送事件
flatMapLatest → 只保留最新请求
debounce → 防抖
flowOn → 切线程

三十二、面试高频回答模板

如果面试问:Flow 有什么用?

可以这样答:

Flow 是 Kotlin 协程提供的异步数据流,用于替代传统 Callback、LiveData、部分 RxJava。

Flow 支持:持续数据发送、协程挂起、操作符链式调用、线程切换、异常处理。

Android 项目中:通常 Repository 返回 Flow,ViewModel 使用 StateFlow 管理 UI 状态,SharedFlow 处理一次性事件。

常见场景:网络请求、搜索防抖、Room 数据监听、Compose 状态更新、WebSocket、分页加载。

Google 官方目前推荐:Flow + StateFlow 作为现代 Android 响应式方案。

相关推荐
xingpanvip1 分钟前
星盘接口开发文档:马盘次限盘接口指南
android·开发语言·python·php·lua
FBI HackerHarry浩2 分钟前
第二阶段Day07【Python生成器、yield关键字、property、正则表达式】
开发语言·python·正则表达式
iiiiyu10 分钟前
IO流(二)
java·开发语言·数据结构·编程语言
白露与泡影10 分钟前
牛客网大厂Java面试题全集(2026版,附答案)
java·开发语言
零点一顿微胖14 分钟前
[Agent]实现获取系统基本信息接口 Rust版
开发语言·rust
Java面试题总结32 分钟前
AgentScope Harness 深度实战:让Java智能体从“Demo可用”走向“生产可用”
java·开发语言·wpf
玖釉-35 分钟前
Vulkan 中 Shader 的 vert、frag、mesh、comp 全面解析:作用、关系、特点与工程实践
开发语言·c++·windows·算法·图形渲染
用户26190498561571 小时前
JUnit4 完整配置流程
android
用户26190498561571 小时前
JaCoCo 完整配置流程
android
陕西企来客1 小时前
2026 西安 GEO 优化技术解析:前沿技术与行业规范深度企来客科技行业白皮书声明
开发语言·搜索引擎·php