Coroutines 在 Android 中的应用
1. 为什么在 Android 中使用协程?
在 Android 开发中,协程(Coroutines)是处理异步任务的现代解决方案,相比传统方式(如 Thread、AsyncTask、RxJava),具有以下优势:
- 简化异步代码:用同步写法处理异步逻辑,避免回调地狱。
- 轻量级:协程是线程之上的封装,切换开销远低于线程。
- 结构化并发:通过作用域(
CoroutineScope)管理生命周期,避免内存泄漏。 - 与 Jetpack 组件深度集成:如
ViewModel、Lifecycle和Room均内置协程支持。
2. 基本用法
2.1 添加依赖
在 build.gradle 中引入协程库:
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
}
2.2 在 ViewModel 中使用协程
class MyViewModel : ViewModel() {
private val repository = DataRepository()
// 使用 viewModelScope 自动取消协程
fun fetchData() {
viewModelScope.launch(Dispatchers.IO) {
val result = repository.loadData() // 挂起函数
withContext(Dispatchers.Main) {
updateUI(result) // 切换回主线程更新 UI
}
}
}
}
2.3 处理网络请求
结合 Retrofit 使用挂起函数:
interface ApiService {
@GET("users")
suspend fun getUsers(): List<User> // 挂起函数
}
// ViewModel 中调用
viewModelScope.launch {
try {
val users = apiService.getUsers()
_userList.value = users
} catch (e: Exception) {
_errorMessage.value = "Network error"
}
}
3. 生命周期管理
3.1 与 Lifecycle 集成
使用 lifecycle-runtime-ktx 扩展:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// 仅在 STARTED 状态时执行协程
observeData()
}
}
}
}
3.2 避免内存泄漏
- 使用
viewModelScope或lifecycleScope:协程会随组件生命周期自动取消。 - 避免全局作用域:
GlobalScope不会绑定生命周期,需手动管理。
4. 高级场景
4.1 并发任务组合
使用 async 并行执行任务:
viewModelScope.launch {
val deferred1 = async { fetchUserProfile() }
val deferred2 = async { fetchUserPosts() }
val profile = deferred1.await()
val posts = deferred2.await()
showCombinedData(profile, posts)
}
4.2 超时处理
viewModelScope.launch {
try {
val result = withTimeout(5000) { // 5秒超时
fetchSlowData()
}
} catch (e: TimeoutCancellationException) {
showError("Request timed out")
}
}
5. 常见问题与最佳实践
5.1 线程切换
- 主线程:
Dispatchers.Main(更新 UI) - IO 操作:
Dispatchers.IO(网络、数据库) - 计算密集型任务:
Dispatchers.Default(CPU 密集型计算)
5.2 异常处理
- 使用
try-catch捕获协程内异常。 - 通过
CoroutineExceptionHandler全局处理未捕获异常。
5.3 测试协程
使用 TestCoroutineDispatcher 和 runTest(需添加 kotlinx-coroutines-test 依赖):
@Test
fun testFetchData() = runTest {
val viewModel = MyViewModel(testDispatcher)
viewModel.fetchData()
advanceUntilIdle() // 等待所有协程完成
assertEquals(expectedData, viewModel.data.value)
}
总结
协程为 Android 开发提供了简洁、高效的异步编程方案,结合 Jetpack 组件和 Kotlin 语言特性,能显著提升代码可读性和可维护性。关键点:
- 优先使用
viewModelScope/lifecycleScope。 - 合理选择调度器(
Dispatchers)。 - 通过结构化并发避免资源泄漏。
