Appearance
09. Kotlin 协程详解
目录
- 协程基础概念
- 协程 vs 传统线程
- CoroutineScope 作用域
- Job 生命周期管理
- Dispatchers 调度器
- launch vs async 对比
- 协程取消机制
- 异常处理
- 协程调度器自定义
- 结构化并发
- 协程泄漏检测
- 性能优化
- 面试考点
1. 协程基础概念
1.1 什么是协程
协程(Coroutine) 是 Kotlin 提供的一种轻量级线程,用于简化异步编程。协程允许以同步的代码风格编写异步代码,通过挂起和恢复机制实现非阻塞操作。
kotlin
// 协程的基本概念
import kotlinx.coroutines.*
suspend fun myCoroutine() {
// 这是一个挂起函数
delay(1000) // 非阻塞延迟
println("Coroutine executed")
}
fun main() = runBlocking {
// runBlocking 是一个协程构建器
myCoroutine()
}1.2 协程的核心组件
kotlin
// 协程三要素:
// 1. Scope (作用域) - 协程的生命周期容器
// 2. Job (作业) - 协程的执行任务
// 3. Dispatcher (调度器) - 协程运行的线程池
coroutineScope {
// Scope 定义协程的作用域
launch(Dispatchers.Default) { // Dispatcher 指定调度器
// Job 自动创建并管理
delay(1000)
println("Work done")
}
}1.3 挂起函数(suspend)
kotlin
// 挂起函数:可以挂起而不阻塞线程的函数
suspend fun fetchUserData(): User {
// 挂起操作,不会阻塞线程
delay(1000)
return User("Alice", 30)
}
// 只能在协程或其他挂起函数中调用
fun main() = runBlocking {
val user = fetchUserData() // ✅ 正确
}
// ❌ 错误:不能在普通函数中调用挂起函数
// fun regularFunction() {
// fetchUserData() // 编译错误
// }1.4 协程构建器
kotlin
// 主要协程构建器
coroutineScope {
// 轻量级作用域,等待所有子协程完成
}
supervisorScope {
// 异常隔离的作用域
}
withContext(Dispatchers.IO) {
// 切换上下文执行
}
runBlocking {
// 阻塞当前线程直到协程完成
}2. 协程 vs 传统线程
2.1 资源对比
| 特性 | 线程 | 协程 |
|---|---|---|
| 内存占用 | 1MB+ | KB 级别 |
| 创建开销 | 高 | 极低 |
| 切换开销 | 高(内核态) | 低(用户态) |
| 并发能力 | 百级别 | 百万级别 |
| 管理复杂度 | 高 | 低 |
2.2 代码对比
kotlin
// 传统线程方式
fun traditionalAsync() {
Thread {
println("Working in thread")
Thread.sleep(1000)
println("Done")
}.start()
}
// 协程方式
suspend fun coroutineAsync() {
println("Working in coroutine")
delay(1000) // 非阻塞
println("Done")
}
// 多线程 vs 多协程
fun traditionalMultiThread() {
val threads = listOf(1, 2, 3, 4, 5).map { i ->
Thread {
Thread.sleep(1000)
println("Thread $i done")
}
}
threads.forEach { it.start() }
threads.forEach { it.join() }
}
suspend fun coroutineMultiCoroutine() {
listOf(1, 2, 3, 4, 5).forEach { i ->
launch {
delay(1000)
println("Coroutine $i done")
}
}
}2.3 阻塞 vs 非阻塞
kotlin
// 传统线程 - 阻塞
fun blockingOperation() {
println("Start")
Thread.sleep(1000) // 阻塞线程 1 秒
println("End")
}
// 协程 - 非阻塞
suspend fun nonBlockingOperation() {
println("Start")
delay(1000) // 挂起,不阻塞线程
println("End")
}
fun main() = runBlocking {
println("Before")
nonBlockingOperation()
println("After") // 立即执行,不等待 1 秒
}2.4 性能对比测试
kotlin
fun benchmarkThreads() {
val iterations = 10000
val start = System.currentTimeMillis()
repeat(iterations) {
Thread {
Thread.sleep(1)
}.start()
}
val end = System.currentTimeMillis()
println("Threads: ${end - start} ms")
}
suspend fun benchmarkCoroutines() {
val iterations = 10000
val start = System.currentTimeMillis()
repeat(iterations) {
launch {
delay(1)
}
}
val end = System.currentTimeMillis()
println("Coroutines: ${end - start} ms")
}
// 典型结果:
// Threads: 100+ ms(线程创建开销大)
// Coroutines: 10+ ms(协程创建开销小)3. CoroutineScope 作用域
3.1 作用域的基本概念
kotlin
// CoroutineScope 是协程的容器
interface CoroutineScope {
val coroutineContext: CoroutineContext
}
// 作用域包含:
// 1. Job - 生命周期管理
// 2. Dispatcher - 线程调度
// 3. ExceptionHandler - 异常处理3.2 创建作用域
kotlin
// 1. 临时作用域
coroutineScope {
// 等待所有子协程完成
launch { /* ... */ }
launch { /* ... */ }
} // 等待完成后才继续
// 2. 结构化作用域
supervisorScope {
// 异常不会传播到父协程
launch { /* ... */ }
}
// 3. 长期作用域
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)3.3 作用域的生命周期
kotlin
class ViewModel : ViewModel() {
// ViewModel 的作用域,随 ViewModel 销毁
val viewModelScope = CoroutineScope(SupervisorJob())
init {
viewModelScope.launch {
// 协程在 ViewModel 销毁时自动取消
loadData()
}
}
override fun onCleared() {
super.onCleared()
viewModelScope.cancel() // 取消所有协程
}
}3.4 作用域传播
kotlin
// 父作用域的上下文会传播到子协程
coroutineScope {
launch {
// 继承父作用域的 Job 和 Dispatcher
println(coroutineContext)
}
}
// 可以覆盖继承的上下文
coroutineScope(Dispatchers.IO) {
launch(Dispatchers.Main) { // 覆盖为 Main
println(coroutineContext)
}
}3.5 作用域取消传播
kotlin
// 父作用域取消,所有子协程也会取消
val scope = CoroutineScope(Job())
scope.launch {
launch {
// 子协程
println("Child running")
}
}
// 取消父作用域
scope.cancel()
// 所有子协程都会被取消4. Job 生命周期管理
4.1 Job 状态
kotlin
// Job 的状态
enum class JobState {
NEW, // 新建
CREATED, // 已创建
ACTIVE, // 活跃
COMPLETING, // 完成中
COMPLETED, // 已完成
CANCELLED, // 已取消
CANCELLING, // 取消中
FAILED // 失败
}
// 状态检查
val job = launch {
// ...
}
println(job.isActive) // true - 是否活跃
println(job.isCompleted) // false - 是否完成
println(job.isCancelled) // false - 是否取消
println(job.isCancelledOrCompleted) // false4.2 Job 等待
kotlin
// 等待协程完成
val job = launch {
delay(1000)
println("Done")
}
job.join() // 阻塞等待完成
// 或使用
job.await() // 挂起等待
// 非阻塞等待
job.invokeOnCompletion {
println("Job completed: $it")
}4.3 Job 取消
kotlin
// 取消协程
val job = launch {
repeat(1000) { i ->
delay(100)
println("Processing: $i")
}
}
delay(500)
job.cancel() // 取消协程
// 取消并清理
job.cancelAndJoin()
// 取消原因
job.cancel(CancellationException("User cancelled"))4.4 Job 层次结构
kotlin
// 父子关系
val parent = launch {
val child1 = launch {
// 子协程 1
}
val child2 = launch {
// 子协程 2
}
// 等待子协程
child1.join()
child2.join()
}
// 取消父协程,子协程也会被取消
parent.cancel()4.5 Job 监控
kotlin
class JobMonitor {
private val jobs = mutableListOf<Job>()
fun track(job: Job) {
jobs.add(job)
job.invokeOnCompletion { exception ->
jobs.remove(job)
if (exception != null) {
println("Job failed: $exception")
}
}
}
fun cancelAll() {
jobs.forEach { it.cancel() }
jobs.clear()
}
fun activeCount(): Int = jobs.count { it.isActive }
}5. Dispatchers 调度器
5.1 内置调度器
kotlin
// Dispatchers.Main - 主线程
launch(Dispatchers.Main) {
// UI 更新操作
textView.text = "Hello"
}
// Dispatchers.Default - 默认调度器(计算密集型)
launch(Dispatchers.Default) {
// 计算密集型任务
val result = heavyComputation()
}
// Dispatchers.IO - IO 密集型
launch(Dispatchers.IO) {
// 网络请求、文件读写
val data = readFile()
}
// Dispatchers.Unconfined - 无限制
launch(Dispatchers.Unconfined) {
// 不限制线程,不推荐在 Android 中使用
}5.2 调度器对比
kotlin
// Dispatchers.Default
// - 使用 CPU 核心数的线程池
// - 适用于计算密集型任务
// - 默认调度器
// Dispatchers.IO
// - 使用大量线程(通常 64 或设备核心数 * 32)
// - 适用于 IO 密集型任务
// - 线程可以阻塞
// Dispatchers.Main
// - 单线程(主线程)
// - 适用于 UI 更新
// - Android 中自动配置
// Dispatchers.Unconfined
// - 不限定线程
// - 在哪个线程开始就在哪个线程继续
// - 不推荐使用(可能导致线程混乱)5.3 切换上下文
kotlin
// 在协程中切换调度器
suspend fun loadData() = withContext(Dispatchers.IO) {
// IO 操作
val data = api.fetchData()
withContext(Dispatchers.Default) {
// 计算操作
data.process()
}
withContext(Dispatchers.Main) {
// UI 更新
updateUI(data)
}
}
// 使用 launch 指定调度器
launch(Dispatchers.IO) {
val data = fetchData()
withContext(Dispatchers.Main) {
updateUI(data)
}
}5.4 调度器性能
kotlin
// Default 调度器 - CPU 核心数线程
fun testDefaultDispatcher() = runBlocking {
repeat(100) { i ->
launch(Dispatchers.Default) {
delay(10)
println("Default: $i")
}
}
}
// IO 调度器 - 大量线程
fun testIODispatcher() = runBlocking {
repeat(1000) { i ->
launch(Dispatchers.IO) {
delay(10)
println("IO: $i")
}
}
}
// Main 调度器 - 单线程
fun testMainDispatcher() = runBlocking {
repeat(10) { i ->
launch(Dispatchers.Main) {
println("Main: $i")
}
}
}5.5 调度器顺序
kotlin
// Default -> Main 的顺序优化
suspend fun fetchDataAndShow(): User {
return withContext(Dispatchers.Default) {
// 先切换到 Default 进行计算
val user = api.fetchUser()
processUser(user)
}
// 自动切换回原来的上下文(通常是 Main)
}
// 显式顺序
suspend fun explicitOrder(): User {
return withContext(Dispatchers.IO) {
withContext(Dispatchers.Default) {
withContext(Dispatchers.Main) {
// 最后在主线程执行
}
}
}
}6. launch vs async 对比
6.1 核心区别
kotlin
// launch - -fire and forget(不返回值)
val job = launch {
delay(1000)
println("Launched")
}
// async - 返回值(Deferred<T>)
val deferred = async {
delay(1000)
"Async result"
}
val result = deferred.await()6.2 使用场景
kotlin
// launch 场景:不需要结果
launch {
// 日志记录
logEvent("User clicked")
// 推送通知
sendNotification("New message")
// 更新数据库
saveToDatabase(data)
}
// async 场景:需要结果
val deferred1 = async {
fetchUser()
}
val deferred2 = async {
fetchPosts()
}
val user = deferred1.await()
val posts = deferred2.await()6.3 并行执行
kotlin
// 并行执行多个异步任务
suspend fun parallelExecution() {
val deferred1 = async { fetchUser() }
val deferred2 = async { fetchPosts() }
val deferred3 = async { fetchComments() }
// 等待所有任务完成
val user = deferred1.await()
val posts = deferred2.await()
val comments = deferred3.await()
// 组合结果
showUserWithPostsAndComments(user, posts, comments)
}
// 使用 awaitAll
suspend fun parallelWithAwaitAll() {
val deferreds = listOf(
async { fetchUser() },
async { fetchPosts() },
async { fetchComments() }
)
val results = awaitAll(*deferreds.toTypedArray())
}6.4 错误处理差异
kotlin
// launch 的错误会传播到父协程
launch {
throw Exception("Launch error") // 父协程会捕获
}
// async 的错误延迟到 await 时抛出
val deferred = async {
throw Exception("Async error") // 在 await 时抛出
}
try {
deferred.await()
} catch (e: Exception) {
println("Caught: ${e.message}")
}6.5 性能对比
kotlin
// launch 性能(无返回值开销)
suspend fun benchmarkLaunch() {
val jobs = listOf(1..1000).map { i ->
launch {
delay(1)
}
}
jobs.forEach { it.join() }
}
// async 性能(有返回值开销)
suspend fun benchmarkAsync() {
val deferreds = listOf(1..1000).map { i ->
async {
delay(1)
i
}
}
deferreds.forEach { it.await() }
}
// async 比 launch 慢约 10-20%(由于返回值包装)6.6 结构化并发
kotlin
// launch 和 async 都支持结构化并发
coroutineScope {
val job1 = launch { /* ... */ }
val job2 = launch { /* ... */ }
// 等待所有子协程完成
}
coroutineScope {
val deferred1 = async { /* ... */ }
val deferred2 = async { /* ... */ }
// 等待所有子协程完成
val result1 = deferred1.await()
val result2 = deferred2.await()
}7. 协程取消机制
7.1 取消原理
kotlin
// 协程取消通过抛异常实现
suspend fun cancellableOperation() {
repeat(1000) { i ->
// 检查取消
ensureActive() // 如果已取消,抛出 CancellationException
delay(100) // delay 内部会检查取消
println("Processing: $i")
}
}
// delay 的取消检查
suspend fun delay(ms: Long) {
// 内部实现会定期检查 isCancelled
// 如果取消,抛出 CancellationException
}7.2 取消传播
kotlin
// 父协程取消,子协程也会取消
val parent = CoroutineScope(Job())
parent.launch {
launch {
// 子协程 1
}
launch {
// 子协程 2
}
}
parent.cancel() // 所有子协程都会被取消7.3 可取消操作
kotlin
// 可取消的协程操作
suspend fun cancellableFetch() {
withContext(Dispatchers.IO) {
// IO 操作可以被取消
val data = api.fetchData()
}
}
// 不可取消的操作(需要特殊处理)
suspend fun nonCancellableFetch() {
// 普通线程操作不会自动取消
Thread {
Thread.sleep(1000) // 不会响应协程取消
}.join()
}
// 可取消的线程操作
suspend fun cancellableThreadOperation() {
val job = Job()
val thread = Thread {
// 线程工作
}
try {
withContext(job) {
thread.join()
}
} finally {
thread.interrupt() // 中断线程
}
}7.4 取消处理
kotlin
// 捕获取消异常
suspend fun handleCancellation() {
try {
launch {
delay(1000)
}.join()
} catch (e: CancellationException) {
println("Cancelled: ${e.message}")
}
}
// 忽略取消
suspend fun ignoreCancellation() {
try {
// 操作
} catch (e: CancellationException) {
// 忽略
}
}
// 重新抛出取消
suspend fun rethrowCancellation() {
try {
// 操作
} catch (e: CancellationException) {
throw e // 重新抛出
}
}7.5 取消最佳实践
kotlin
// 最佳实践 1:使用 cancelAndJoin
val job = launch {
// ...
}
job.cancelAndJoin() // 取消并等待完成
// 最佳实践 2:使用 withTimeout
suspend fun withTimeoutExample() {
withTimeout(1000) {
// 1 秒内完成,否则取消
longRunningOperation()
}
}
// 最佳实践 3:使用 SupervisorJob 隔离取消
supervisorScope {
launch {
// 失败不会取消其他协程
}
launch {
// 失败不会取消其他协程
}
}8. 异常处理
8.1 异常传播
kotlin
// launch 的异常传播到父协程
launch {
throw Exception("Error") // 父协程会捕获
}
// async 的异常延迟到 await
val deferred = async {
throw Exception("Error") // await 时抛出
}
try {
deferred.await()
} catch (e: Exception) {
println("Caught: ${e.message}")
}8.2 SupervisorJob 异常隔离
kotlin
// 使用 SupervisorJob 隔离异常
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
throw Exception("Child 1 error")
} catch (e: Exception) {
println("Child 1: ${e.message}")
}
}
scope.launch {
// 不会受到 Child 1 异常影响
println("Child 2 running")
}
// SupervisorJob 的异常不会传播到父协程
supervisorScope {
launch {
throw Exception("Error") // 不会取消其他协程
}
launch {
// 继续执行
}
}8.3 try-catch 处理
kotlin
// 在协程中使用 try-catch
suspend fun safeOperation() {
try {
riskyOperation()
} catch (e: Exception) {
println("Error: ${e.message}")
}
}
// 在 launch 中处理
launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Launch error: ${e.message}")
}
}
// 在 async 中处理
val deferred = async {
try {
riskyOperation()
} catch (e: Exception) {
defaultValue
}
}8.4 全局异常处理
kotlin
// 设置全局异常处理器
CoroutineScope(
SupervisorJob() +
Dispatchers.Default +
CoroutineExceptionHandler { _, exception ->
println("Unhandled exception: $exception")
}
) {
launch {
throw Exception("Global error")
}
}
// 在 Android 中
class GlobalExceptionHandler : CoroutineExceptionHandler {
override fun handleException(context: CoroutineContext, exception: Throwable) {
// 记录日志
Timber.e(exception)
// 显示错误
showError(exception.message)
}
}8.5 异常恢复
kotlin
// 使用 retry 恢复
suspend fun <T> retry(
times: Int = 3,
delay: Duration = 1.second,
block: suspend () -> T
): T {
repeat(times) { attempt ->
try {
return block()
} catch (e: Exception) {
if (attempt == times - 1) throw e
delay(delay)
}
}
throw IllegalStateException("Should not reach here")
}
// 使用
suspend fun fetchWithRetry() {
val data = retry(times = 3) {
api.fetchData()
}
}9. 协程调度器自定义
9.1 创建自定义调度器
kotlin
// 使用 Executors 创建
val customDispatcher = Executors.newFixedThreadPool(10).asCoroutineDispatcher()
// 使用 CoroutineDispatcher
val myDispatcher = MyCoroutineDispatcher()
class MyCoroutineDispatcher : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) {
// 自定义调度逻辑
threadPool.execute(block)
}
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
// 是否需要切换上下文
return !isSameThread()
}
}9.2 调度器参数
kotlin
// 有限制的调度器
val limitedDispatcher = Dispatchers.Default.limitedParallelism(4)
// 带延迟的调度器
val delayedDispatcher = Dispatchers.Default.limitedParallelism(
parallelism = 4,
capacity = 100,
onCapacityExceeded = {
println("Capacity exceeded")
}
)9.3 调度器关闭
kotlin
// 关闭自定义调度器
val dispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
coroutineScope(dispatcher) {
launch {
// 使用自定义调度器
}
}
dispatcher.close() // 关闭调度器9.4 调度器调试
kotlin
// 调度器名称
val namedDispatcher = newFixedThreadPool(4,
ThreadFactory { runnable ->
Thread(runnable, "My-Dispatcher-${threadCount.getAndIncrement()}")
}
).asCoroutineDispatcher()
// 调度器监控
class DispatcherMonitor {
fun monitor(dispatcher: CoroutineDispatcher) {
// 监控调度器状态
}
}10. 结构化并发
10.1 结构化并发原理
kotlin
// 结构化并发:协程作为构建块
coroutineScope {
// 所有子协程都是这个作用域的一部分
// 父作用域等待所有子协程完成
launch { /* ... */ }
launch { /* ... */ }
} // 等待所有子协程完成10.2 结构化并发示例
kotlin
// 典型的结构化并发场景
suspend fun fetchUserData(): UserData {
return coroutineScope {
val userDeferred = async { fetchUser() }
val postsDeferred = async { fetchPosts() }
val commentsDeferred = async { fetchComments() }
UserData(
user = userDeferred.await(),
posts = postsDeferred.await(),
comments = commentsDeferred.await()
)
}
}10.3 取消传播
kotlin
// 结构化并发的取消传播
coroutineScope {
val job1 = launch {
delay(1000)
println("Job 1")
}
val job2 = launch {
delay(2000)
println("Job 2")
}
// 取消作用域
cancel()
// job1 和 job2 都会被取消
}10.4 错误隔离
kotlin
// 使用 supervisorScope 错误隔离
supervisorScope {
launch {
throw Exception("Job 1 error")
}
launch {
// 继续执行,不受 Job 1 错误影响
println("Job 2 running")
}
}11. 协程泄漏检测
11.1 泄漏原因
kotlin
// 泄漏原因 1:未等待协程完成
fun leakyFunction() {
launch {
// 协程在函数返回后继续运行
}
// 函数返回,协程可能泄漏
}
// 泄漏原因 2:持有协程引用
class LeakyClass {
val jobs = mutableListOf<Job>()
fun addJob() {
val job = launch { /* ... */ }
jobs.add(job) // 持有引用,无法 GC
}
}11.2 检测方法
kotlin
// 使用 Android Profiler 检测
// 1. 内存分析
// 2. 线程分析
// 3. CPU 分析
// 代码检测
fun checkLeakedCoroutines() {
val activeJobs = coroutineContext[Job]?.children?.toList()
if (activeJobs != null) {
println("Active jobs: ${activeJobs.size}")
}
}11.3 预防泄漏
kotlin
// 预防 1:使用结构化并发
coroutineScope {
// 自动等待所有子协程
}
// 预防 2:及时取消
val job = launch { /* ... */ }
// 在不需要时取消
job.cancel()
// 预防 3:使用 viewModelScope
class ViewModel : ViewModel() {
// viewModelScope 在 ViewModel 销毁时自动取消
viewModelScope.launch {
// 安全
}
}11.4 泄漏调试
kotlin
// 添加调试日志
class DebugCoroutineScope(private val scope: CoroutineScope) {
fun launch(block: suspend CoroutineScope.() -> Unit): Job {
val job = scope.launch {
println("Coroutine started: ${coroutineContext}")
try {
block()
} finally {
println("Coroutine finished: ${coroutineContext}")
}
}
return job
}
}12. 性能优化
12.1 减少协程创建
kotlin
// 优化 1:复用协程
val sharedScope = CoroutineScope(Dispatchers.Default)
// 优化 2:批量处理
suspend fun batchProcess(items: List<Item>) {
items.chunked(100).forEach { batch ->
batch.forEach { item ->
process(item)
}
}
}12.2 调度器优化
kotlin
// 使用合适的调度器
suspend fun optimizedOperation() {
withContext(Dispatchers.IO) {
// IO 操作
}
withContext(Dispatchers.Default) {
// 计算操作
}
}12.3 内存优化
kotlin
// 避免持有协程引用
class OptimizedClass {
private val scope = CoroutineScope(Dispatchers.Default)
fun process() {
scope.launch {
// 不保存 job 引用
}
}
}12.4 并发控制
kotlin
// 使用 Semaphore 控制并发
val semaphore = Semaphore(10)
suspend fun controlledConcurrent(items: List<Item>) {
items.forEach { item ->
withSemaphore(semaphore) {
process(item)
}
}
}13. 面试考点
13.1 基础考点
Q1: 什么是协程?它与线程的区别?
A:
- 协程是轻量级的线程,在用户态运行
- 线程在内核态,协程在用户态
- 协程创建开销小,线程创建开销大
- 协程切换开销小,线程切换开销大
Q2: 协程的三大组件?
A:
- Scope(作用域)- 协程的生命周期容器
- Job(作业)- 协程的执行任务
- Dispatcher(调度器)- 协程运行的线程
Q3: suspend 函数的作用?
A:
- 标记函数可以挂起
- 只能在协程或其他挂起函数中调用
- 不阻塞线程,只是暂停执行
13.2 进阶考点
Q4: launch 和 async 的区别?
A:
- launch 返回 Job,不返回值
- async 返回 Deferred,需要 await 获取结果
- launch 用于 fire-and-forget
- async 用于需要结果的场景
Q5: 结构化并发的原理?
A:
- 父协程等待所有子协程完成
- 子协程的异常会传播到父协程
- 取消父协程会取消所有子协程
13.3 高级考点
Q6: 协程取消机制的实现?
A:
- 通过抛 CancellationException 实现
- delay 等挂起函数会检查取消状态
- 确保协程可以安全地取消
Q7: 如何实现协程泄漏检测?
A:
- 使用 Android Profiler
- 检查未完成的 Job
- 使用 DebugCoroutineScope 添加日志
Q8: 协程性能优化策略?
A:
- 减少协程创建
- 使用合适的调度器
- 避免持有协程引用
- 使用批量处理
总结
Kotlin 协程是异步编程的革命性工具,通过轻量级线程和挂起恢复机制,提供了简洁高效的并发编程方式。掌握协程的核心概念、生命周期管理、异常处理和性能优化,是成为高级 Android 开发者的必备技能。
核心要点:
- 轻量级 - 协程比线程更轻量
- 非阻塞 - delay 不阻塞线程
- 结构化并发 - 清晰的协程层次
- 异常处理 - SupervisorJob 隔离异常
- 性能优化 - 合理使用调度器