Android面试冲击附答案(八)————Flow

3 阅读5分钟

Android面试冲击附答案(八)————Flow


一、面试题与答案

1. Flow 是什么?有什么特性?和普通挂起函数区别?
  • Flow 是 Kotlin 协程体系中的异步数据流抽象。
  • 特性:可组合操作符、背压支持、取消传播、上下文透明。
  • 与普通 suspend 区别:
    • suspend 通常返回单次结果
    • Flow 表示0~N 次连续数据
2. 什么是冷流和热流?
  • 冷流(如 flow {}):订阅才生产,一般一对一。
  • 热流(如 SharedFlow/StateFlow):可独立于订阅持续存在,一对多广播。
3. SharedFlow、StateFlow 区别和场景?
  • SharedFlow:事件流,无必须初值,可配置 replay,适合一次性事件/广播。
  • StateFlow:状态流,必须初值,replay=1 且状态去重,适合 UI 状态。
4. Flow 上下文保留(Context Preservation)是什么?为什么 flow{} 里不能随意 withContext?
  • flow {} 的执行上下文应保持透明,通常由收集端决定。
  • 上下文切换建议用 flowOn(作用于上游),而不是在 flow {} 内随意 withContext 破坏语义。
5. Flow 异常透明性(Exception Transparency)是什么?

上游异常应由下游显式处理,避免静默吞异常,保证流的可预测性。 常用:catch {}onCompletion {}、外层 try-catch

6. flowOf/asFlow/flow/channelFlow 区别?
  • flowOf():固定值快速建流。
  • asFlow():集合/序列转 Flow。
  • flow {}:最常用,顺序发射。
  • channelFlow {}:支持多协程并发发送,适合多源并发场景。
7. flowOn() 作用?影响上游还是下游?

flowOn 只影响上游执行上下文,不影响下游 collect 所在上下文。

8. buffer/conflate/collectLatest 区别与背压处理?
  • buffer:缓存排队,尽量不丢数据。
  • conflate:只保留最新值,丢旧值。
  • collectLatest:新值到来时取消旧消费任务。
9. buffer() 和 SharedFlow.extraBufferCapacity 区别?
  • buffer():冷流链路中的临时缓冲。
  • extraBufferCapacitySharedFlow 自身缓冲配置,生命周期随热流存在。
10. map/filter/transform/flatMapConcat/flatMapMerge/flatMapLatest 区别?
  • map 转换;filter 过滤;transform 可灵活多次发射。
  • flatMapConcat 串行有序。
  • flatMapMerge 并发,结果可乱序。
  • flatMapLatest 保留最新,取消旧任务。
11. catch() 能捕获上游还是下游异常?

catch 主要捕获上游异常;下游 collect {} 内业务异常通常需外层自己处理。

12. Flow 常见副作用操作符有哪些?

onStartonEachonCompletiononEmpty 等。 它们通常不改变主数据,只做日志、埋点、loading、清理等副作用。

13. retry() 和 retryWhen() 区别?
  • retry():简单重试,灵活度低。
  • retryWhen():可按异常类型、次数、延迟策略(含退避)自定义。
14. zip() 和 combine() 区别?
  • zip:一一配对。
  • combine:任一上游更新就与另一个“最新值”组合。
15. stateIn()/shareIn() 与 SharingStarted 三策略?
  • stateIn/shareIn:把冷流热化。
  • Eagerly:立即启动。
  • Lazily:首个订阅时启动。
  • WhileSubscribed:有订阅才运行,无订阅可停止,UI 场景常用。
16. SharedFlow 参数 replay / extraBufferCapacity / onBufferOverflow 作用?
  • replay:新订阅者可回放条数。
  • extraBufferCapacity:额外缓冲。
  • onBufferOverflow:溢出策略(挂起/丢最旧/丢最新)。
17. emit() 和 tryEmit() 区别?
  • emit():挂起发送,必要时等待。
  • tryEmit():非挂起,失败返回 false,适合不阻塞发送端场景。
18. SharedFlow 默认配置多消费者问题?

默认无缓冲时,慢消费者可能反压发送端,导致发送端性能问题。多消费者通常需合理配置缓冲与溢出策略。

19. subscriptionCount 有什么用?

表示活跃订阅数量,可用于按订阅数决定是否生产数据或管理资源启停。

20. resetReplayCache() 有什么作用?

清空 SharedFlow 的 replay 缓存,影响后续新订阅者读取到的历史事件。

21. SharedFlow never completes 是什么意思?

SharedFlow 作为热流通常不会自然终止,通常随作用域结束而结束。

22. StateFlow 为什么必须有初始值?

因为它表达“当前状态”,语义上必须始终可读到一个值。

23. StateFlow.value 和 collect 区别?
  • .value:同步读取当前快照。
  • collect:异步持续监听后续变化。
24. StateFlow 重复 emit 相同值会通知吗?

通常不会。StateFlow 具备类似 distinctUntilChanged 的状态去重语义。

25. compareAndSet() 是什么?

MutableStateFlow.compareAndSet 提供原子更新语义,适合并发安全状态更新。

26. Android 中收集 Flow 为什么不能只用 lifecycleScope.launch?

launch 可能在不可见状态仍收集;应配合 repeatOnLifecycle 按生命周期自动启停。

27. repeatOnLifecycle / flowWithLifecycle / launchWhenX 区别?
  • repeatOnLifecycle:块级控制,离开状态会取消并重建,官方首选。
  • flowWithLifecycle:单 Flow 生命周期感知封装。
  • launchWhenX:挂起恢复模型,资源释放不如前两者彻底。
28. Flow 取消后,正在执行的 emit 会怎样?

取消后后续挂起点(含 emit)会抛 CancellationException 并终止后续链路;onCompletion 仍会执行清理。

29. channelFlow 和 flow 区别?什么时候必须用 channelFlow?
  • flow:单协程串行发射。
  • channelFlow:可多协程并发发送。

必须用 channelFlow 的典型场景:多源并发生产、回调桥接、多线程发送。

30. Flow 是线程安全的吗?为什么 FlowCollector 非线程安全?

Flow 作为声明式流模型可线程切换,但 flow {}emit 默认要求顺序语义,FlowCollector 非并发发送模型;并发发送应转 channelFlow

31. Flow 和 Channel 区别?
  • Flow:偏声明式数据流处理,操作符丰富。
  • Channel:偏消息管道,手动收发、关闭与背压控制更底层。
32. 如何实现防抖和节流?
  • 防抖:debounce()
  • 节流:Flow 官方无统一内建 throttleFirst,通常自定义实现。

二、Flow原理

1) 角色说明

角色职责典型对象
生产者发射数据flow { emit(...) }
中间操作符转换/过滤/合并map/filter/flatMap/combine
收集者消费数据collect/collectLatest
上下文切换器调整上游线程flowOn
热化容器多订阅共享stateIn/shareIn/SharedFlow/StateFlow

2) 冷流与热流关系图

冷流 Flow
collect() 才启动
   |
   +--> 每个订阅者独立执行上游

热流 SharedFlow/StateFlow
创建后可持续存在
   |
   +--> 多订阅者共享同一数据源

3) 执行链路图

emit --> map --> filter --> buffer/conflate --> collect
          |                         |
       数据变换                 背压调节

4) 高频对应关系

需求推荐方案说明
UI 状态StateFlow有初值、状态语义清晰
一次性事件SharedFlow可配置 replay/缓冲
生命周期收集repeatOnLifecycle避免后台无效收集
上游切线程flowOn(IO)仅影响上游
高频输入搜索debounce + flatMapLatest自动淘汰旧请求
多源并发发射channelFlow并发安全发送