1、什么是 Flow?
答案
Flow 是 Kotlin 协程流式异步数据流 ,可以连续发送多个数据,是冷数据流。
可以理解为:异步数据流,一条流水线,源源不断发数据、处理数据、接收数据。
基于协程,全程挂起非阻塞,优雅替代回调、RxJava。## 2、Flow 三大组成部分
2、Flow 三大组成部分
答案
- 生产者:flow {emit () } 发射数据
- 中间操作符 :map、filter、flatMapConcat 等,懒执行、不触发消费
- 消费者:collect 收集处理数据
3、冷流 Cold Flow 是什么?特点
答案 默认普通 Flow 都是冷流。特点:
- 没人订阅不生产数据
- 每一次 collect 都会从头重新发射
- 单订阅模式,每个消费者独立拿到完整数据流适合:一次性请求、本地查询、网络请求。
4、热流 Hot Flow 是什么?特点
答案
不管有没有订阅者,都一直在发数据。
多观察者共享同一条数据流,不会重新从头发射。
代表:SharedFlow、StateFlow。适合:全局消息、事件总线、UI 状态常驻。
5、StateFlow 详细讲解
答案
- 属于热流
- 永远保存当前最新状态值
- 默认粘性,新订阅者立刻收到最新值
- 类似 LiveData
- 要求有初始值适用:UI 界面状态、页面数据、开关状态。
6、SharedFlow 详细讲解
答案
- 属于热流
- 不强制有初始值
- 可自定义 replay 重播数量
- 可以实现无粘性单次事件适用:弹窗提示、页面跳转、按钮点击、消息通知。
7、Cold Flow 和 Hot Flow 核心区别
答案
- 冷流:不订阅不发数据;热流:一直在发
- 冷流每次订阅从头开始;热流共享数据流
- 冷流一对一;热流一对多广播
- 普通 flow 是冷流;SharedFlow/StateFlow 是热流
8、flowOn 作用
答案
指定 上游生产者 执行的线程。
- 只影响 flow {}、map、filter 等上游
- 不影响下游 collect 下游切线程要用
launchIn或自己切协程调度器。
9、launchIn 作用
答案
把 Flow 绑定到指定 协程作用域 自动收集,不用手写 collect。
常用:
launchIn(lifecycleScope)launchIn(viewModelScope)自动跟随生命周期取消,防泄漏。
10、repeatOnLifecycle 作用(高频)
答案
让 Flow 感知页面生命周期:
- 页面后台:自动暂停数据流
- 页面前台:自动恢复
- 页面销毁:自动取消
好处:省电、减少无用回调、彻底杜绝内存泄漏。
11、MutableSharedFlow 和 SharedFlow 区别
答案
- MutableSharedFlow:可变,可手动 emit 发事件
- SharedFlow:只读,只能订阅不能发规范:对外暴露只读 SharedFlow,内部用 MutableSharedFlow。
12、MutableStateFlow 和 StateFlow 区别
答案
- MutableStateFlow:可以修改 value
- StateFlow:只读规范同 LiveData:内部可变、外部只读。
13、Flow 操作符分类(面试常问)
答案
转换:map、transform、flatMapConcat、flatMapLatest
过滤:filter、distinctUntilChanged
限流:debounce 防抖、sample 采样
组合:zip、combine
生命周期:repeatOnLifecycle、launchIn
14、flatMapConcat /flatMapLatest 区别
答案
- flatMapConcat:按顺序逐个执行,前一个完再执行下一个
- flatMapLatest:新事件来了直接取消上一个,只保留最新(搜索框联想最常用)
15、Flow 和 LiveData 详细对比(必背)
答案
- 定位
- LiveData:UI 状态持有者
- Flow:通用异步数据流
- 粘性
- LiveData 强制粘性
- Flow 可自由控制有无粘性
- 生命周期
- LiveData 自带生命周期感知
- Flow 默认无,需手动 repeatOnLifecycle
- 能力
- LiveData 功能简单
- Flow 操作符丰富,支持复杂流式处理
- 适用场景
- LiveData:简单 UI 状态
- Flow:网络流、事件、防抖、连续数据、复杂异步
16、Flow 会不会内存泄漏?什么情况会漏
答案会。
泄漏场景:
- 不用作用域管理,全局一直 collect
- 没有绑定 lifecycleScope /viewModelScope
- 没有用 repeatOnLifecycle避免:一定要绑定生命周期协程作用域。
17、Flow 为什么比 LiveData 适合做一次性事件
答案
LiveData 天生粘性,页面重建、重新观察都会重复触发弹窗、跳转;
SharedFlow 可以设置 replay=0,无粘性,只响应一次事件,完美解决重复触发问题。
18、Flow 和 RxJava 对比
答案
- Flow 是 Kotlin 原生;RxJava 第三方库
- Flow 语法更简洁,协程无缝结合
- Flow 轻量;RxJava 笨重、学习成本高
- Flow 生命周期更好管理;RxJava 需要手动 Disposable现在项目 Flow 完全替代 RxJava。
19、Flow 挂起原理
答案
Flow 基于协程 suspend 函数,emit、collect 都是挂起函数;
不会阻塞线程,只是挂起协程,利用状态机切换执行步骤,实现异步无回调。
20、Flow 必须 collect 吗?
普通冷 Flow 必须 collect,不 collect 永远不执行;
热流 SharedFlow/StateFlow 不用 collect 也能自己发数据。
普通冷 Flow 必须 collect 才会执行 ,不订阅不发数据;可以用 launchIn 代替手动写 collect;而 SharedFlow、StateFlow 是热流,不用 collect 也能正常产生数据。
21、面试一句话总结完整版
Flow 是 Kotlin 协程异步流式框架,分冷流和热流;普通 Flow 是冷流,不订阅不发数据;SharedFlow、StateFlow 是热流,支持多观察者共享;StateFlow 类似 LiveData 适合 UI 状态,SharedFlow 适合无粘性一次性事件;通过 flowOn 切上游线程,launchIn 绑定作用域,repeatOnLifecycle 感知生命周期自动暂停取消,功能比 LiveData 更强、替代 RxJava 做复杂异步流。
22、 observeAsState和collectAsStateWithLifecycle 的区别
1. observeAsState(适配 LiveData)
- 作用 :专门用于将 Android 传统的
LiveData转换为 Compose 的State对象,让 LiveData 的数据变化自动驱动 UI 重组。 - 本质 :是 LiveData 针对 Compose 的扩展函数,内部会自动观察 LiveData 的变化,并将最新值包装成
State(Compose 能感知的状态)。 - 核心特点:依赖 LiveData 的生命周期感知能力(但需要手动关联 LifecycleOwner)。
2. collectAsStateWithLifecycle(适配 Flow/StateFlow/SharedFlow)
- 作用 :专门用于将 Kotlin Flow(尤其是冷流)转换为 Compose 的
State对象,且自带生命周期感知(仅在组件处于活跃状态时收集数据)。 - 本质 :是 Flow 针对 Compose + 生命周期的扩展函数,基于
repeatOnLifecycle实现,能自动在组件(如 Activity/Fragment)进入STARTED状态时开始收集数据,进入STOPPED状态时暂停收集,避免后台浪费资源或内存泄漏。 - 核心特点:专为 Kotlin 协程 Flow 设计,生命周期感知更安全(Jetpack 官方推荐)。