Android 使用 Kotlin 协程例子
协程是一种并发设计模式,您可以在 Android 平台上使用它来简化异步执行的代码,协程是我们在 Android 上进行异步编程的推荐解决方案
- 轻量:您可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作
- 内存泄露更少:使用结构化并发机制在一个作用域内执行多个操作。
- 内置取消支持:取消功能会自动通过正在运行的协程层次结构传播
4.Jetpack 集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发
实例
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
// Create a new coroutine to move the execution off the UI thread
viewModelScope.launch(Dispatchers.IO) {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
loginRepository.makeLoginRequest(jsonBody)
}
}
}
下面我们仔细分析一下 login 函数中的协程代码:
- viewModelScope 是预定义的 CoroutineScope,包含在 ViewModel KTX 扩展中。请注意,所有协程都必须在一个作用域内运行。一个 CoroutineScope 管理一个或多个相关的协程。
- launch 是一个函数,用于创建协程并将其函数主体的执行分派给相应的调度程序。
- Dispatchers.IO 指示此协程应在为 I/O 操作预留的线程上执行。
上面三个类就是协程中最重要的内容: coroutineScope; launch() 方法, Dispatchers
使用协程确保主线程安全
如果函数不会在主线程上阻止界面更新,我们即将其视为是主线程安全的。makeLoginRequest 函数不是主线程安全的,因为从主线程调用 makeLoginRequest 确实会阻塞界面。可以使用协程库中的 withContext() 函数将协程的执行操作移至其他线程:
class LoginRepository(...) {
...
suspend fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
// Move the execution of the coroutine to the I/O dispatcher
return withContext(Dispatchers.IO) {
// Blocking network request code
}
}
}
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
// Create a new coroutine on the UI thread
viewModelScope.launch {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
// Make the network call and suspend execution until it finishes
val result = loginRepository.makeLoginRequest(jsonBody)
// Display result of the network request to the user
when (result) {
is Result.Success<LoginResponse> -> // Happy path
else -> // Show error in UI
}
}
}
}
示例中,协程是在 LoginViewModel 中创建的。由于 makeLoginRequest 将执行操作移出主线程,login 函数中的协程现在可以在主线程中执行: