Kotlin 协程面试题大全(Android 高频版)

Kotlin 协程面试题大全(Android 高频版)

这一篇不是只背答案,而是:

真正理解协程面试底层逻辑

内容包括:协程基础、suspend 原理、Continuation、Dispatcher、Job、Flow、Retrofit、Room、Compose、高频陷阱题、Android 实战。


一、什么是协程?

标准回答

Kotlin 协程是一种:轻量级线程

它可以:

  • 挂起
  • 恢复
  • 非阻塞执行异步任务

核心目标: 用同步代码写异步逻辑

加分回答

协程本质:Continuation + 状态机

不是线程,而是编译器生成的状态机对象。


二、协程和线程区别?

对比 线程 协程
创建成本 很低
调度 OS调度 用户态调度
阻塞 容易阻塞 挂起不阻塞
数量 可非常多
切换成本 极低

高频一句话

协程运行在线程上,但不是线程。


三、什么是 suspend?

标准回答

suspend 表示:函数可以挂起,不会阻塞线程。

加分回答

suspend 编译后会变成:Continuation 参数,即 CPS(Continuation Passing Style)转换


四、suspend 是否会自动开线程?

标准答案

不会。

高频误区

很多人以为:suspend = 异步线程 --- 错误。

正确理解

suspend 只是支持:挂起与恢复 ,是否异步取决于 launch / async / Dispatcher


五、delay 为什么不卡线程?

标准答案

因为 delay 挂起的是协程,不是线程。

底层流程

复制代码
保存Continuation
    ↓
线程释放
    ↓
时间到
    ↓
resume恢复

六、Thread.sleep 和 delay 区别?

对比 Thread.sleep delay
阻塞线程
阻塞协程
是否释放线程

高频一句话

sleep 卡线程,delay 不卡线程。


七、launch 和 async 区别?

launch async
无返回值 有返回值
返回 Job 返回 Deferred
kotlin 复制代码
// launch
launch { }

// async
val result = async { }.await()

八、withContext 和 launch 区别?

launch withContext
开启新协程 切换线程并等待结果

高频点: withContext 是 suspend,会等待执行完成。


九、CoroutineScope 是什么?

标准答案

协程必须运行在 CoroutineScope 中,负责:

  • 生命周期
  • Job 管理
  • 协程取消

十、GlobalScope 为什么不推荐?

原因: 生命周期不可控,容易内存泄漏。

不推荐 Android 推荐
GlobalScope viewModelScope / lifecycleScope

十一、协程取消原理?

标准答案

协程是:协作式取消,不是线程强杀。

原理: 挂起点 delay() / yield() 会检查 isActive


十二、为什么 while(true) cancel 不掉?

错误

kotlin 复制代码
while(true) { }

因为没有检查取消状态。

正确

kotlin 复制代码
while(isActive) { }

十三、Job 是什么?

标准答案

每个协程都有 Job,作用:cancel / join / 父子协程管理


十四、SupervisorJob 是什么?

普通 Job SupervisorJob
一个子协程失败,全部取消 子协程互不影响

Android 高频使用。


十五、CoroutineContext 是什么?

标准答案

协程上下文,内部保存:

  • Dispatcher
  • Job
  • CoroutineName
  • ExceptionHandler

本质: Map 结构


十六、Dispatchers 有哪些?

Dispatcher 用途
Main 主线程
IO IO操作
Default CPU密集型
Unconfined 不推荐

十七、Dispatchers.IO 和 Default 区别?

IO Default
网络、数据库、文件 CPU计算、排序、JSON解析

十八、withContext(IO) 为什么常用?

因为:避免主线程阻塞

kotlin 复制代码
withContext(Dispatchers.IO) {
    // 网络/数据库操作
}

十九、Retrofit 为什么支持 suspend?

标准答案

Retrofit 底层拿到了 Continuation,网络完成后调用 resume() 恢复协程。


二十、Retrofit suspend 为什么不卡主线程?

因为:OkHttp异步线程池 + Continuation恢复


二十一、Room 为什么查询用 Flow?

因为:查询是持续变化的数据源,适合 Flow。


二十二、为什么 insert/update/delete 用 suspend?

因为:一次性操作,不需要持续数据流。


二十三、Flow 是冷流还是热流?

默认 Flow 是:冷流(Cold Flow)

意思: 没人 collect 就不会执行。


二十四、StateFlow 是什么?

热流(Hot Flow)

特点:

  • 有初始值
  • 永远活着
  • 保存最新值

二十五、SharedFlow 是什么?

用于事件流,例如:Toast、Snackbar、页面跳转


二十六、StateFlow 和 SharedFlow 区别?

StateFlow SharedFlow
有状态 无状态
必须初始值 不需要
保存最新值 可不保存
UI状态 事件通知

二十七、LiveData 和 Flow 区别?

维度 LiveData Flow
归属 Android 框架组件 Kotlin 协程库
生命周期 自带感知,自动防泄漏 无感知,需要自己结合 repeatOnLifecycle
线程切换 不方便,只能 observe 主线程 天然支持 flowOn 随意切线程
数据变换 只有简单 map、switchMap 算子超多:map/filter/transform/flatMapConcat 等
冷热流 属于热流:有观察者才发数据 默认冷流:没人收集就不生产数据
依赖 安卓专属,离不开 Android 纯 Kotlin,跨平台可用
适用场景 页面 UI 状态简单观察 复杂数据流、连续事件、网络轮询、本地数据库

现代 Android:Flow 已逐渐替代 LiveData,

最简总结

  • LiveData:专为UI 观察设计,生命周期感知,只能在主线程用,功能简单。
  • Flow:Kotlin 协程的数据流,跨线程、可变换、可链式操作、功能更强,不绑定 UI,全场景通用。
  • 新项目直接 抛弃 LiveData,用 StateFlow 代替

二十八、collect 和 collectLatest 区别?

collect collectLatest
前一个没结束,后一个等待 新数据到来,取消旧任务

搜索场景高频使用。


二十九、flatMapLatest 为什么重要?

核心作用: 自动取消旧请求

搜索框场景: 用户输入 a → ab → abc,旧搜索自动取消。


三十、Compose 中为什么不能直接 launch?

因为:Compose 会重组,可能重复创建协程。

正确: LaunchedEffect / rememberCoroutineScope


三十一、LaunchedEffect 和 rememberCoroutineScope 区别?

API 用途
LaunchedEffect 自动生命周期协程
rememberCoroutineScope 用户事件协程

三十二、collectAsState 本质?

Flow → Compose State(把 Flow 数据流,变成 Compose 能刷新 UI 的 State 变量。),Flow emit 时自动重组 UI。


三十三、协程为什么轻量?

因为:本质只是对象 + 状态机,不是 OS 线程。


三十四、Continuation 是什么?

协程执行现场,保存:

  • label(状态机位置)
  • 局部变量
  • 执行位置

三十五、协程为什么能恢复?

因为:continuation.resume()


三十六、label 是什么?

状态机位置

label 位置
0 开始
1 delay后
2 第二次挂起后

三十七、协程本质是什么?

编译器把 suspend 转成状态机 ,核心是 Continuation + resume + 状态机


三十八、为什么 suspend 只能在协程里调用?

因为:需要 Continuation,普通函数没有。


三十九、Flow 为什么默认不卡线程?

因为:Flow 本身不指定线程,线程由 flowOn() 决定。


四十、flowOn 和 withContext 区别?

flowOn withContext
改变上游线程 改变当前协程线程

四十一、为什么推荐 viewModelScope?

因为:生命周期自动管理,ViewModel 销毁时协程自动 cancel。


四十二、协程异常传播?

  • 普通: 子协程异常 → 父协程取消
  • SupervisorJob: 互不影响

四十三、CoroutineExceptionHandler 有什么用?

全局协程异常处理

kotlin 复制代码
CoroutineExceptionHandler { _, e ->
    // 全局处理
}

四十四、企业级最佳实践(高频)

不要
GlobalScope viewModelScope
UI直接请求网络 UI → ViewModel → Repository → Retrofit/Room

四十五、终极面试题(压轴)

Kotlin 协程本质是什么?

推荐答案:

Kotlin 协程本质是:编译器把 suspend 函数转换成状态机,通过 Continuation 保存执行现场,在挂起后通过 resume 恢复执行,从而实现非阻塞异步编程。


四十六、真正的大脑模型(最重要)

看到 自动想到
suspend Continuation + 状态机
delay() 挂起协程,不阻塞线程
Flow 持续数据流
StateFlow Compose UI状态

最后一段(真正拉开差距)

普通开发者 高级开发者
会写 launch 理解 Continuation + 状态机 + Flow + 响应式架构 + Compose状态驱动

真正决定你水平的,不是会不会 API,而是你是否真正理解协程运行机制。

相关推荐
集成显卡3 分钟前
Rust实战七 |基于带 colored 颜色文字控制台的批量文件删除工具
开发语言·后端·rust
折翅鵬8 分钟前
Android史诗级网络优化实践总结
android·网络
比昨天多敲两行1 小时前
linux 线程概念与控制
java·开发语言·jvm
huaweichenai1 小时前
php 根据每个类型的抽签范围实现抽签功能
开发语言·php
赏金术士2 小时前
Android 项目模块化与 Feature 组件实践
android·kotlin·模块化
codeejun2 小时前
每日一Go-73、云原生成本优化 —— 资源限制 & 指标驱动扩容
开发语言·云原生·golang
就叫_这个吧3 小时前
Java注解、元注解、自定义注解定义及应用
java·开发语言·注解
Sam_Deep_Thinking3 小时前
聊聊Java中的of
java·开发语言·架构
_qingche6 小时前
H2 数据库到 MySQL 数据迁移
java·数据库·spring boot·mysql·spring·重构·kotlin
小小de风呀6 小时前
de风——【从零开始学C++】(十一):list的基本使用和模拟实现
开发语言·c++·list