Kotlin中协程的关键函数分析

在 Kotlin 中,协程的关键函数主要来自 kotlinx.coroutines 库。

1,协程作用域(Scopes)

CoroutineScope(context: CoroutineContext):定义协程的作用域,用于管理协程的启动和取消。创建独立的协程作用域,所有子协程完成前不会结束。

scss 复制代码
import kotlinx.coroutines.CoroutineScope

val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
coroutineScope.launch {...}
coroutineScope.async {...}
coroutineScope.cancel() // 取消所有子协程

在compose中,

ini 复制代码
import androidx.compose.runtime.rememberCoroutineScope

val coroutineScope = rememberCoroutineScope()
coroutineScope.launch {...}
coroutineScope.async {...}

supervisorScope:子协程失败不会全部取消,即子协程异常不影响其他子协程。

scss 复制代码
import kotlinx.coroutines.supervisorScope
supervisorScope {
    launch { task1() } // 失败不会取消其他子协程
    launch { task2() }
}

2,协程构建器(Coroutine Builders)

用于启动新协程的核心函数:launch, async, runBlocking.

launch(context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit): Job

启动一个不阻塞当前线程的新协程(通常用于执行后台任务,不返回结果),返回一个 Job 对象用于管理协程生命周期(如取消)。

scss 复制代码
val job = CoroutineScope(Dispatchers.Main).launch {
    delay(1000)
    println("Done")
}
job.join() // 等待协程完成

async 启动一个可返回结果的协程(通过 Deferred 对象获取结果)。

async(context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T): Deferred

启动一个返回 Deferred 结果的协程,可通过 .await() 获取结果。

dart 复制代码
val deferred = scope.async { 
    // 执行计算
}
val result = deferred.await() // 获取结果(会挂起协程)

runBlocking,其用途是在非协程环境中启动协程,会阻塞当前线程直到协程完成。 主要场景用于测试或启动主协程。

runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T

阻塞当前线程直到协程完成,常用于测试或主函数入口。即runBlocking 在阻塞当前线程的上下文中启动协程(主要用于测试或 main 函数)。

3,上下文切换与调度 核心函数是withContext和Dispatchers

withContext(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T withContext 临时切换协程的上下文(如线程池),执行完成后返回结果。

withContext其用途是在指定的调度器中执行代码块,并返回结果。其特点是会挂起当前协程,但不会阻塞线程。

kotlin 复制代码
scope.launch {
    val result = withContext(Dispatchers.IO) { 
        // 在 IO 线程执行阻塞操作
        fetchData() 
    }
    // 自动切回原上下文
}

import kotlinx.coroutines.*

suspend fun fetchData(): String = withContext(Dispatchers.IO) {
    // 模拟IO操作
    delay(1000)
    "Data from IO thread"
}

调度器(Dispatchers):

Dispatchers.Default:CPU 密集型任务(线程池)

Dispatchers.IO:I/O 阻塞操作(优化后的线程池)

Dispatchers.Main:Android 主线程(需依赖 kotlinx-coroutines-android)

Dispatchers.Unconfined:不限制执行线程(谨慎使用)

4,挂起函数(Suspending Functions)

在Kotlin协程中,每一个挂起函数都会被编译成一个状态机,其中每个挂起点都会分割成多个部分。每个部分都是一个 Continuation ,当挂起函数需要恢复执行时,就会调用Continuation 的 resume 方法。

kotlin 复制代码
interface Continuation<in T> {
	val context: CoroutineContext
	fun resume(value: T) // resume用于成功恢复协程的执行,并传递一个结果值。
	fun resumeWithException(exception: Throwable) // 以异常恢复挂起的协程,用于恢复协程的执行,但传递一个异常,导致协程在挂起点抛出该异常。
}

resume和resumeWithException 方法通常与 suspendCoroutine 构建器配合使用,suspendCoroutine用于手动控制协程恢复的底层构建器。

kotlin 复制代码
suspend fun fetchData(): String = suspendCoroutine { cont ->
    // 模拟异步回调
    thread {
        Thread.sleep(1000)
        if (success) {
            cont.resume("Data received") // 成功恢复
        } else {
            cont.resumeWithException(IOException()) // 失败恢复
        }
    }
}

一般推荐使用 suspendCancellableCoroutine。

kotlin 复制代码
suspend fun downloadFile(): ByteArray = suspendCancellableCoroutine { cont ->
    val call = apiService.downloadFile().enqueue(
        object : Callback {
            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    cont.resume(response.body())
                } else {
                    cont.resumeWithException(HttpException(response))
                }
            }
            override fun onFailure(call: Call, t: Throwable) {
                cont.resumeWithException(t)
            }
        })
    
    // 提供取消支持
    cont.invokeOnCancellation { call.cancel() }
}

协程中可暂停执行的函数,使用 suspend 关键字修饰。

delay(timeMillis: Long):非阻塞式挂起协程指定时间,释放线程供其他任务使用。

yield():主动挂起协程,让出当前协程执行权,允许同一线程的其他协程运行(常用于公平调度)。

5, 取消与异常处理

cancel(cause: CancellationException? = null):取消协程或作用域内的所有协程,释放资源。即cancel()取消协程(通过 Job 对象)。

scss 复制代码
val job = scope.launch { ... }
job.cancel() // 取消协程
scope.cancel() // 取消作用域内所有协程

suspendCancellableCoroutine

用途:将回调式 API 转换为协程式 API。

kotlin 复制代码
suspend fun getUserData(userId: String): User = suspendCancellableCoroutine { continuation ->
    // 假设这是一个回调式 API
    userRepository.getUser(userId) { user, error ->
        if (error != null) {
            continuation.resumeWithException(error)
        } else {
            continuation.resume(user)
        }
    }
}

isActive:检查协程是否仍处于活动状态。

while (isActive) { ... } // 在取消时自动退出循环

ensureActive():如果协程已取消,立即抛出 CancellationException。 ensureActive() // 手动检查取消状态

withTimeout():设置协程执行超时 withTimeout(3000) { // 超时抛出 TimeoutCancellationException longRunningTask() }

CoroutineExceptionHandler:全局异常处理器(非函数,但需配合协程使用)

scss 复制代码
val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}
CoroutineScope(Dispatchers.Main + handler).launch {
    throw RuntimeException("Error") // 异常会被 handler 捕获
}

6,流处理(Flow API)

flow { ... }:创建冷流(Cold Stream)。

scss 复制代码
fun getDataFlow() = flow {
    emit(1)
    emit(2)
}

collect():收集流的值。

scss 复制代码
scope.launch {
    getDataFlow().collect { 
		value -> println(value)
    }
}

6,关键概念总结

函数/概念 作用

launch: 启动不返回结果的协程

async + await: 启动可返回结果的协程

runBlocking: 阻塞线程直到协程完成(用于测试)

withContext: 切换协程上下文(如线程池)

coroutineScope: 创建结构化并发作用域(子协程失败会传播取消) supervisorScope:子协程失败不会传播取消

delay: 非阻塞挂起

cancel + isActive: 协程取消控制

Flow: 异步流处理(类似 RxJava)

相关推荐
FunnySaltyFish13 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker19 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z4 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton4 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream5 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam5 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker5 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc5 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景6 天前
kotlin协程学习小计
android·kotlin