1. Kotlin协程基础从线程到协程的思维转变第一次接触Kotlin协程时我习惯性地用线程的思维去理解它结果踩了不少坑。后来才明白协程和线程根本是两种不同的并发模型。线程是操作系统层面的概念由系统内核调度而协程是用户态的轻量级线程由程序自己控制调度。举个生活中的例子线程就像银行柜台每个柜台同时只能服务一个客户单核CPU情况下系统负责安排客户到不同柜台。协程则像餐厅服务员一个服务员可以轮流照顾多桌客人 - 点完A桌的菜趁等菜时间去B桌倒水再回A桌上菜。这种协作式的工作方式就是协程的精髓。协程的三大核心优势轻量级我在测试中创建了10万个协程仅消耗约1GB内存而同样数量的线程直接导致OOM崩溃低成本切换协程上下文切换不需要内核参与比线程切换快10倍以上结构化并发通过作用域管理生命周期避免内存泄漏// 传统线程实现 thread { val data fetchDataFromNetwork() // 网络请求 runOnUiThread { updateUI(data) // 更新UI } } // 协程实现 lifecycleScope.launch(Dispatchers.IO) { val data fetchDataFromNetwork() withContext(Dispatchers.Main) { updateUI(data) } }2. Coroutine核心机制解析2.1 协程作用域CoroutineScope作用域是协程最重要的概念它决定了协程的生命周期。我在项目中曾因为错误使用GlobalScope导致内存泄漏后来改用lifecycleScope才解决问题。常见作用域类型GlobalScope慎用生命周期与应用一致容易内存泄漏lifecycleScope与Activity/Fragment生命周期绑定viewModelScope在ViewModel清除时自动取消自定义作用域通过CoroutineScope()创建需手动管理class MyActivity : AppCompatActivity() { // 正确用法使用lifecycleScope override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycleScope.launch { // 当activity销毁时自动取消 loadData() } } }2.2 协程上下文与调度器调度器决定协程运行在哪个线程上我常用的有四种Dispatchers.MainAndroid主线程用于UI操作Dispatchers.IO适合磁盘/网络IODispatchers.DefaultCPU密集型计算Dispatchers.Unconfined不指定线程慎用lifecycleScope.launch(Dispatchers.Main) { // 在主线程启动 val result withContext(Dispatchers.IO) { // 切换到IO线程执行耗时操作 performNetworkRequest() } // 自动切回主线程更新UI updateViews(result) }3. Channel协程间的通信管道Channel让我想起了生产线上的传送带不同工序的工人协程可以通过传送带传递半成品。我在实现下载管理器时就用Channel实现了生产者-消费者模式。Channel的四种容量类型RENDEZVOUS默认无缓冲发送接收要同时就绪BUFFERED固定大小缓冲默认64UNLIMITED无限缓冲CONFLATED新值覆盖旧值val channel ChannelInt(Channel.BUFFERED) // 生产者协程 launch { repeat(10) { channel.send(it) delay(100) } channel.close() } // 消费者协程 launch { for (item in channel) { println(Received: $item) } }实际应用场景实时数据传输如聊天消息事件总线替代方案限制并发数的任务队列4. Flow响应式编程的协程实现Flow就像一条数据河流可以经过各种操作符filter/map等的加工最终被收集collect。我在项目中用Flow重构了原本基于RxJava的代码性能提升了15%。4.1 冷流与热流冷流每次收集都会重新发射数据如数据库查询热流不管有没有收集者都会发射数据如传感器数据// 冷流示例 fun getUsers(): FlowUser flow { val users userDao.getAll() users.forEach { emit(it) } } // 转换为热流 val sharedFlow getUsers().shareIn( scope viewModelScope, started SharingStarted.WhileSubscribed(5000), replay 1 )4.2 Flow操作符实战常用操作符链userFlow .filter { it.isActive } .map { it.toDisplayModel() } .catch { e - emit(defaultUser) } .onEach { Log.d(Flow, User: $it) } .launchIn(lifecycleScope)性能优化技巧使用buffer()减少背压用flowOn指定上游操作的调度器复杂转换考虑使用channelFlow5. 协程在Android中的最佳实践5.1 网络请求封装我封装了一个基于协程的网络请求工具类suspend fun T safeApiCall( call: suspend () - T ): ResultT withContext(Dispatchers.IO) { try { Result.Success(call()) } catch (e: Exception) { Result.Error(e) } } // 使用示例 viewModelScope.launch { when (val result safeApiCall { api.getUser() }) { is Result.Success - _user.value result.data is Result.Error - _error.value result.exception } }5.2 结合Jetpack组件LiveData使用liveData构建器val user: LiveDataUser liveData { emit(loadUser()) emitSource(userDao.observeUser()) }Room直接返回FlowDao interface UserDao { Query(SELECT * FROM user) fun observeUsers(): FlowListUser }5.3 常见坑与解决方案内存泄漏避免使用GlobalScope改用生命周期感知的作用域主线程阻塞长时间运行的任务要切到IO或Default调度器异常处理使用CoroutineExceptionHandler或supervisorScope取消传播定期检查isActive或调用yield()// 正确处理取消 lifecycleScope.launch { while (isActive) { // 检查活动状态 doWork() delay(1000) // 可取消的挂起函数 } }