协程是 Kotlin 提供的一套简化异步编程的轻量级线程操作框架,特别适合 Android 开发中的异步任务处理。以下是 Android 开发中需要掌握的协程核心知识点:
1. 协程基础概念
1.1 协程是什么
轻量级线程:比线程更高效,可以在单个线程中运行多个协程
可挂起恢复:可以在不阻塞线程的情况下挂起和恢复执行
结构化并发:提供更好的生命周期管理和错误处理机制
1.2 基本组件
// 启动协程的三种方式
launch { /* 启动不返回结果的协程 */ }
async { /* 启动可返回结果的协程 */ }
runBlocking { /* 阻塞当前线程直到协程完成 */ }
2. 协程构建器
2.1 基本构建器
// 在ViewModel中启动协程
viewModelScope.launch {
// 协程体
}
// 在Activity/Fragment中启动协程
lifecycleScope.launch {
// 自动跟随生命周期取消
}
// 全局协程
GlobalScope.launch {
// 不推荐在Android中使用,容易内存泄漏
}
2.2 带返回值的构建器
val deferred = viewModelScope.async {
delay(1000)
"Result"
}
// 获取结果
val result = deferred.await()
3. 协程上下文与调度器
3.1 常用调度器
Dispatchers.Main // 主线程,更新UI
Dispatchers.IO // IO操作
Dispatchers.Default // CPU密集型计算
Dispatchers.Unconfined // 不指定线程(不推荐)
3.2 上下文组合
viewModelScope.launch(Dispatchers.IO + CoroutineName("MyCoroutine")) {
println("Running in ${Thread.currentThread().name}")
}
4. 协程取消与异常处理
4.1 取消协程
val job = viewModelScope.launch {
repeat(1000) { i ->
ensureActive() // 检查是否被取消
delay(500)
println("Job: I'm sleeping $i ...")
}
}
// 取消协程
job.cancel()
4.2 异常处理
viewModelScope.launch {
try {
val result = withContext(Dispatchers.IO) {
fetchData() // 可能抛出异常
}
} catch (e: Exception) {
// 处理异常
}
}
// 使用SupervisorJob防止异常传播
val scope = CoroutineScope(SupervisorJob())
5. 协程与Android架构组件
5.1 ViewModel集成
class MyViewModel : ViewModel() {
fun fetchData() {
viewModelScope.launch {
try {
val data = repository.getData()
_uiState.value = UiState.Success(data)
} catch (e: Exception) {
_uiState.value = UiState.Error(e.message)
}
}
}
}
5.2 Lifecycle集成
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// 只在STARTED状态收集流
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
}
}
6. 协程与网络请求
6.1 Retrofit集成
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") userId: String): User
}
// 使用
viewModelScope.launch {
try {
val user = apiService.getUser("123")
_user.value = user
} catch (e: Exception) {
_error.value = e.message
}
}
6.2 并行请求
viewModelScope.launch {
val userDeferred = async { apiService.getUser(userId) }
val postsDeferred = async { apiService.getPosts(userId) }
val user = userDeferred.await()
val posts = postsDeferred.await()
_result.value = UserWithPosts(user, posts)
}
7. 协程与Room数据库
7.1 DAO定义
@Dao
interface UserDao {
@Insert
suspend fun insert(user: User)
@Query("SELECT * FROM users")
fun getAllUsers(): Flow<List<User>>
}
7.2 使用示例
viewModelScope.launch {
// 插入数据
userDao.insert(User(name = "John"))
// 观察数据变化
userDao.getAllUsers().collect { users ->
_users.value = users
}
}
8. 协程与Flow
8.1 创建Flow
fun countDownFlow(): Flow<Int> = flow {
val countDownFrom = 10
for (i in countDownFrom downTo 0) {
delay(1000)
emit(i)
}
}
8.2 收集Flow
viewModelScope.launch {
countDownFlow().collect { time ->
_countDown.value = time
}
}
8.3 Flow操作符
viewModelScope.launch {
(1..5).asFlow()
.filter { it % 2 == 0 }
.map { it * it }
.collect { println(it) } // 输出 4, 16
}
9. 协程最佳实践
避免GlobalScope:使用viewModelScope或lifecycleScope
主线程安全:使用withContext切换调度器
取消传播:确保协程可以正确取消
异常处理:为重要操作添加try-catch
避免阻塞:使用delay而非Thread.sleep
测试:使用TestCoroutineDispatcher进行单元测试
10. 协程测试
@ExperimentalCoroutinesApi
class MyViewModelTest {
@get:Rule
val coroutineRule = MainCoroutineRule()
@Test
fun `test data loading`() = runTest {
val viewModel = MyViewModel(FakeRepository())
viewModel.loadData()
advanceUntilIdle() // 等待所有协程完成
assertEquals(expectedData, viewModel.uiState.value)
}
}
@ExperimentalCoroutinesApi
class MainCoroutineRule : TestWatcher() {
val testDispatcher = StandardTestDispatcher()
override fun starting(description: Description) {
Dispatchers.setMain(testDispatcher)
}
override fun finished(description: Description) {
Dispatchers.resetMain()
}
}
总结
Kotlin协程为Android异步编程提供了强大的解决方案,通过掌握这些核心知识点,您可以:
简化异步代码
避免回调地狱
更好地管理资源
编写更易测试的代码
实现响应式UI更新
在实际开发中,建议结合ViewModel、LiveData/Flow和Retrofit等组件使用协程,构建更健壮的Android应用架构。