1. CoroutineScope
CoroutineScope
是协程运行的范围。每个协程都需要一个 CoroutineScope
,以便管理其生命周期。
kotlin
CoroutineScope(Dispatchers.Default).launch {
// 在此范围内启动一个协程
}
2. Job
Job
是一个协程的句柄,它表示协程的生命周期,并允许显式地取消协程。
kotlin
val job = CoroutineScope(Dispatchers.Default).launch {
// 协程体
}
// 取消协程
job.cancel()
3. Dispatcher
Dispatcher
决定了协程在哪个线程池上执行。常用的 Dispatcher 有:
Dispatchers.Main
- 用于在主线程上执行协程。Dispatchers.IO
- 用于执行 I/O 操作。Dispatchers.Default
- 用于 CPU 密集型任务。
kotlin
CoroutineScope(Dispatchers.IO).launch {
// 在 I/O 线程上运行
}
4. async 和 await
async
用于并发地执行多个任务,并返回一个 Deferred
对象,可以使用 await
来获取结果。
kotlin
val deferred = CoroutineScope(Dispatchers.Default).async {
// 异步计算
42
}
val result = deferred.await()
/Suspend function 'await' should be called only from a coroutine or another suspend function
5. launch
launch
启动一个新的协程,不返回任何结果。
kotlin
CoroutineScope(Dispatchers.Main).launch {
// 在主线程上运行的协程
}
6. withContext
withContext
用于在指定的 Dispatcher
上执行代码块,并返回结果。
kotlin
val result = withContext(Dispatchers.IO) {
// 在 I/O 线程上执行
42
}
7. SupervisorJob
SupervisorJob
是一种特殊类型的 Job
,它的子协程失败不会取消父协程。
kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
scope.launch {
// 子协程1
}
scope.launch {
// 子协程2
}
8. Exception Handling
协程中的异常处理可以使用 try-catch
或 CoroutineExceptionHandler
。
kotlin
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught $exception")
}
CoroutineScope(Dispatchers.Main + handler).launch {
try {
// 协程体
} catch (e: Exception) {
// 处理异常
}
}
9.例子
import kotlinx.coroutines.*
fun main() = runBlocking {
var result: Int = 0
val deferred = CoroutineScope(Dispatchers.Default).async {
delay(1000)
42
}
result = deferred.await()
println(result)
}
Kotlin 的挂起函数(suspend function)用于实现异步编程。挂起函数可以在不阻塞线程的情况下挂起执行,并在稍后恢复。挂起函数使用 suspend
关键字定义。它们只能在协程或另一个挂起函数内调用。
kotlin
suspend fun fetchData(): String {
// 模拟网络请求
delay(1000L)
return "Data from server"
}
挂起函数的特点
- 非阻塞: 挂起函数不会阻塞线程,可以在等待过程中让出线程资源。
- 只能在协程中调用: 由于挂起函数可能会挂起当前的执行,需要在协程或另一个挂起函数中调用。
挂起函数的使用
要使用挂起函数,需要在协程上下文中启动它。常用的协程构建器有 launch
和 async
。
kotlin
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
val result = fetchData()
println(result)
}
}
协程上下文与调度器
协程运行在特定的上下文中,调度器 (Dispatcher) 决定了协程运行的线程或线程池。
Dispatchers.Main
:在主线程上运行,常用于更新 UI。Dispatchers.IO
:适合 IO 操作(如网络或文件操作)。Dispatchers.Default
:适合 CPU 密集型任务。
kotlin
fun main() = runBlocking {
launch(Dispatchers.IO) {
val result = fetchData()
withContext(Dispatchers.Main) {
// 更新 UI
println(result)
}
}
}
挂起函数组合
可以组合多个挂起函数,实现复杂的异步操作。
kotlin
suspend fun fetchUserData(): String {
// 模拟网络请求
delay(1000L)
return "User data"
}
suspend fun fetchAdditionalData(): String {
// 模拟网络请求
delay(1000L)
return "Additional data"
}
fun main() = runBlocking {
launch {
val userData = fetchUserData()
val additionalData = fetchAdditionalData()
println("User Data: $userData, Additional Data: $additionalData")
}
}
异常处理
协程中的异常处理可以使用 try-catch
块。
kotlin
fun main() = runBlocking {
launch {
try {
val result = fetchData()
println(result)
} catch (e: Exception) {
println("Error: ${e.message}")
}
}
}