Android 平台下 Kotlin 协程(coroutines)的使用 ,结合 Android 组件生命周期(Activity/Fragment/ViewModel)、官方最佳实践,从基础依赖、核心概念、组件化用法、实战场景、避坑要点全维度讲解,同时适配 Retrofit 网络框架,替代 RxJava 实现更简洁的异步操作。
协程是 Android 官方唯一推荐 的异步编程方案,相比 Thread/Handler/RxJava,核心优势是语法简洁、非阻塞挂起、自动生命周期绑定(解决内存泄漏)、原生支持 Android 组件 ,下面的内容兼顾基础理解 和生产实战,新手也能快速上手。
一、前置准备:依赖配置与基础要求
1. 核心依赖(必须)
Android 中使用协程需要两个核心依赖,版本必须完全一致 ,同时搭配 Android 官方的lifecycle-ktx(提供组件内置协程作用域,无需手动创建)。截至 2026.02,协程最新稳定版为 1.8.0 ,适配 Kotlin 1.9.0+(Android Studio 新建项目默认适配),配置在模块级build.gradle/build.gradle.kts:
gradle
// Kotlin协程核心(跨平台基础,必选)
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0'
// Kotlin协程Android扩展(Android专属适配,必选)
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0'
// Android生命周期扩展(提供Activity/Fragment/ViewModel内置协程作用域,必选)
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
-
若用Kotlin DSL(build.gradle.kts) ,依赖格式为:
kotlin
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
2. 基础要求(默认满足)
-
Kotlin 版本:1.6.0+(Android Studio 2021.1 + 新建项目默认满足);
-
Android Gradle Plugin:7.0.0+;
-
开启 Java 8 兼容(新建项目默认开启,若未开启需手动配置): gradle
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } // 若用Kotlin,需加这行 kotlinOptions { jvmTarget = "1.8" } }
二、核心概念:3 个必懂知识点(理解后再用)
协程的核心用法围绕 **「作用域、调度器、挂起函数」展开,这 3 个概念是 Android 协程的基础,比 API 更重要,且所有 API 均基于这 3 个概念 **。
1. 协程作用域(CoroutineScope):协程的生命周期管理者
- 核心意义 :所有协程必须在作用域中启动 ,作用域是协程的 "容器",作用域销毁时,其下所有协程会被自动取消 ,从根本上解决 Android 异步操作的内存泄漏问题(这是协程对比 Thread/RxJava 的核心优势)。
- Android 专属福利 :无需手动创建
CoroutineScope,官方为所有核心 Android 组件 提供了内置作用域 (与组件生命周期自动绑定),直接使用即可,这是 Android 协程的标准用法。 - 内置作用域分类 (后续重点讲解):
viewModelScope:ViewModel 的内置作用域,销毁时机为ViewModel.onCleared();lifecycleScope:Activity/Fragment 的内置作用域,销毁时机为onDestroy();
2. 调度器(Dispatchers):指定协程的执行线程
-
核心意义 :调度器用于指定协程在哪个线程执行,通过调度器可轻松实现 **「子线程执行耗时操作,主线程更新 UI」** 的 Android 经典场景。
-
4 个核心调度器 (前 3 个来自
core库,第 4 个来自android库,Android 开发仅用这 4 个):调度器 核心作用 适用场景 Dispatchers.MainAndroid主线程(UI 线程) 更新 UI、调用主线程 API(Toast/View 操作 / Activity 跳转) Dispatchers.IOIO 密集型线程池(子线程) 网络请求、数据库操作、文件读写、SP 存储(Android 最常用) Dispatchers.Default计算密集型线程池(子线程) 数据解析、列表排序、复杂计算(CPU 密集型操作) Dispatchers.Unconfined无指定线程 几乎不使用(易导致线程混乱,仅特殊场景用) -
Android 关键特性 :
viewModelScope/lifecycleScope的默认调度器是Dispatchers.Main(主线程),因此协程启动后默认在主线程执行,无需手动指定。
3. 挂起函数(suspend 关键字):非阻塞的耗时操作
- 核心意义 :用
suspend修饰的函数为挂起函数 ,是协程的核心特性,具备两个关键能力:- 可暂停执行 :在协程中调用挂起函数时,协程会暂停执行 (如等待网络请求 / 数据库查询结果),暂停时不会阻塞线程(线程可继续执行其他协程);
- 自动恢复执行 :挂起函数执行完成(如网络请求拿到结果)后,协程会自动恢复执行,继续执行后续代码。
- 核心规则 :挂起函数仅能在协程中或其他挂起函数中调用,普通函数无法直接调用(这是语法约束,编译器会强制检查)。
- Android 实战 :Retrofit3/ROOM/Glide 等主流库均已对协程做了原生支持 ,提供了现成的挂起函数,无需自己实现(如 Retrofit3 的接口只需加
suspend关键字即可成为挂起函数)。
三、Android 协程的标准用法:3 个内置作用域实战
Android 协程的最佳实践 是直接使用官方内置作用域 ,无需手动创建CoroutineScope,无需手动管理协程生命周期,无需手动取消协程,一行代码启动协程,生命周期自动绑定 。下面按 **「MVVM 开发优先级」讲解 3 个内置作用域的用法, viewModelScope是 MVVM 开发的首选 **(生命周期最长,不受 Activity 重建影响)。
1. viewModelScope:ViewModel 的内置作用域(MVVM 首选)
-
核心特性 :
- 与
ViewModel的生命周期严格绑定 ,ViewModel销毁时(onCleared()),作用域下所有协程自动取消; - 不受 Activity/Fragment 重建影响 (如屏幕旋转 / 切后台导致的 Activity 重建),协程会继续执行,这是
viewModelScope对比lifecycleScope的核心优势; - 默认调度器为
Dispatchers.Main(主线程),无需手动指定;
- 与
-
适用场景 :MVVM 架构中所有异步操作 (网络请求、数据库操作、文件读写),这是 Android 开发的标准用法(将所有业务逻辑放在 ViewModel 中)。
-
实战用法 :直接在 ViewModel 中调用
viewModelScope.launch { ... }即可启动协程,结合withContext切换线程。kotlin
import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope // 导入viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext // 普通ViewModel,无需继承任何额外类,直接用viewModelScope class UserViewModel : ViewModel() { // 登录方法:供View层(Activity/Fragment)调用 fun login(username: String, password: String) { // 1. 启动协程:直接用viewModelScope.launch,默认在主线程执行 viewModelScope.launch { try { // 2. 切换到IO线程执行耗时操作(网络请求):withContext(Dispatchers.IO) // withContext是挂起函数,会暂停协程,执行完成后自动恢复 val loginResult = withContext(Dispatchers.IO) { // 此处执行耗时操作:如Retrofit3网络请求(后续实战讲解) // 模拟网络请求:延迟2秒,返回登录结果 Thread.sleep(2000) // 实际开发用真实挂起函数,禁止用Thread.sleep "登录成功,用户名:$username" } // 3. 自动切回主线程(viewModelScope默认Main),处理结果(如更新数据) // 此处可更新LiveData/StateFlow,供View层观察更新UI println("登录结果:$loginResult") } catch (e: Exception) { // 4. 统一处理异常(网络异常/业务异常等) println("登录失败:${e.message}") } } } } -
View 层(Activity)调用 :直接调用 ViewModel 方法即可,无需关注协程:
kotlin
class LoginActivity : AppCompatActivity() { // 初始化ViewModel private val userViewModel by viewModels<UserViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) // 点击登录按钮,直接调用ViewModel方法 btnLogin.setOnClickListener { val username = etUsername.text.toString().trim() val password = etPassword.text.toString().trim() userViewModel.login(username, password) } } }
2. lifecycleScope:Activity/Fragment 的内置作用域
-
核心特性 :
- 与 Activity/Fragment 的生命周期严格绑定 ,组件销毁时(
onDestroy()),协程自动取消; - 受 Activity/Fragment 重建影响(如屏幕旋转),重建后协程会被取消并重新执行;
- 默认调度器为
Dispatchers.Main(主线程);
- 与 Activity/Fragment 的生命周期严格绑定 ,组件销毁时(
-
适用场景 :仅与页面生命周期相关的异步操作 (如页面可见时刷新 UI、页面销毁前保存临时数据),不建议用于网络请求 / 数据库操作(易因页面重建导致请求中断)。
-
实战用法 :直接在 Activity/Fragment 中调用
lifecycleScope.launch { ... }:kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 启动协程:lifecycleScope lifecycleScope.launch { // 切换到IO线程执行耗时操作 val data = withContext(Dispatchers.IO) { // 模拟文件读写 Thread.sleep(1000) "从文件中读取的内容" } // 切回主线程更新UI tvData.text = data Toast.makeText(this@MainActivity, data, Toast.LENGTH_SHORT).show() } } }
3. 生命周期感知的协程启动(launchWhenXxx)
lifecycleScope提供了 3 个生命周期感知 的扩展方法,让协程仅在指定的生命周期状态执行 ,状态不满足时暂停执行 ,状态恢复时继续执行 ,适合依赖页面可见性的异步操作(如页面可见时才请求数据)。
kotlin
lifecycleScope.launchWhenResumed {
// 仅当页面处于「Resumed」状态(可见、可交互)时执行
// 页面进入Pause状态时,协程暂停;回到Resumed状态时,协程继续执行
val data = withContext(Dispatchers.IO) { api.getData() }
tvData.text = data
}
// 其他两个方法
lifecycleScope.launchWhenCreated { /* 仅Created状态执行 */ }
lifecycleScope.launchWhenStarted { /* 仅Started/Resumed状态执行 */ }
四、核心 API:Android 开发仅用这 5 个(简洁高效)
Android 协程的 API 非常简洁,生产开发中仅需掌握 5 个核心 API,即可覆盖 99% 的场景,所有 API 均基于上述 3 个核心概念,无需记忆复杂 API。
1. launch:启动无返回值的协程(最常用)
- 作用 :启动无返回值的协程,适合执行 "只做不返回" 的操作(如网络请求后更新 UI、文件读写、数据库操作);
- 用法 :
scope.launch { 协程执行体 },scope为内置作用域(viewModelScope/lifecycleScope); - 核心特性 :默认在作用域的默认调度器执行(Main 线程),通过
withContext切换线程。
2. withContext:切换协程的调度器(核心中的核心)
-
作用 :在协程内部切换执行线程 ,执行完成后自动切回原线程 ,是 Android 中 **「子线程执行耗时操作,主线程更新 UI」的唯一方式 **;
-
性质 :挂起函数,会暂停协程,执行完成后恢复;
-
用法 :
withContext(调度器) { 耗时操作 },返回值为耗时操作的结果; -
实战示例 (Android 最经典场景):
kotlin
viewModelScope.launch { // 主线程(默认) val result = withContext(Dispatchers.IO) { // IO子线程:执行网络请求/文件读写 api.login(username, password) // 挂起函数 } // 自动切回主线程:更新UI/处理结果 _userLiveData.value = result }
3. suspend:定义挂起函数(对接第三方库)
- 作用 :修饰函数为挂起函数,让函数具备 "暂停 / 恢复" 能力,可在协程中调用;
- Android 实战 :无需自己实现挂起函数 ,主流第三方库均已提供现成的挂起函数:
-
Retrofit3:接口方法加
suspend关键字即可; -
ROOM:DAO 方法加
suspend关键字即可; -
自己实现挂起函数(仅特殊场景用): kotlin
// 定义挂起函数:模拟网络请求 suspend fun getUserName(): String { // delay是挂起函数,替代Thread.sleep,非阻塞 delay(2000) return "张三" } // 协程中调用 viewModelScope.launch { val name = getUserName() // 直接调用,协程会暂停2秒 tvName.text = name }
-
4. async/await:启动有返回值的协程(并发操作)
-
作用 :启动有返回值 的协程,支持多协程并发执行 ,适合需要同时执行多个异步操作(如同时请求 "用户信息" 和 "订单列表")的场景;
-
用法 :
async { 操作 }启动协程,await()等待协程完成并获取返回值(await()是挂起函数); -
实战示例 (并发网络请求):
kotlin
viewModelScope.launch { // 并发启动2个协程(同时执行,无先后顺序) val userDeferred = async(Dispatchers.IO) { api.getUserInfo() } val orderDeferred = async(Dispatchers.IO) { api.getOrderList() } // 等待两个协程均完成,获取返回值(非阻塞,协程挂起) val user = userDeferred.await() val orderList = orderDeferred.await() // 处理并发结果(主线程) combineData(user, orderList) } -
核心优势 :并发执行的总耗时 = 最慢的那个操作的耗时(如用户请求 2 秒,订单请求 3 秒,总耗时 3 秒),比串行执行(5 秒)效率提升一倍。
5. delay:非阻塞式延迟(替代Thread.sleep)
- 作用 :协程内的非阻塞式延迟 ,用于延迟执行操作,替代
Thread.sleep; - 性质 :挂起函数 ,延迟时不会阻塞线程 (线程可继续执行其他协程),而
Thread.sleep会阻塞线程; - 用法 :
delay(毫秒),如delay(1000)表示延迟 1 秒; - 注意 :协程中禁止使用
Thread.sleep,必须用delay。
五、实战核心:协程与 Retrofit2 的结合(替代 RxJava3)
你之前搭建了 Retrofit2+OkHttp3 的网络框架,Retrofit2 对协程做了原生支持 ,无需 RxJava3 适配器,只需一行代码改造接口 ,即可在协程中直接调用,代码比 RxJava3 更简洁、更易维护。这是 Android 协程的最核心实战场景 ,也是目前生产环境的标准用法。
步骤 1:改造 Retrofit2 接口(添加suspend关键字)
无需修改 Retrofit2 的任何配置(OkHttp 拦截器 / BaseUrl / 转换器均不变),只需在接口方法前添加suspend关键字 ,Retrofit 会自动将该方法转为挂起函数,可在协程中直接调用。
kotlin
// 1. 先定义统一响应体(和你之前的BaseResponse一致)
data class BaseResponse<T>(
val code: Int,
val message: String,
val data: T?
) {
// 判断请求是否成功(根据后端实际成功码修改,如200/0)
fun isSuccess() = code == 200
}
// 2. 改造Retrofit3接口:添加suspend关键字,直接返回BaseResponse<T>
interface UserApi {
// 登录接口:POST请求,添加suspend关键字
@POST("user/login")
suspend fun login(@Body request: LoginRequest): BaseResponse<User>
// 获取用户信息:GET请求,添加suspend关键字
@GET("user/info")
suspend fun getUserInfo(@Query("userId") String userId): BaseResponse<User>
}
// 登录请求体(封装参数)
data class LoginRequest(val username: String, val password: String)
// 业务数据模型
data class User(val userId: String, val name: String, val token: String)
步骤 2:仓库层封装(统一响应体校验 + 异常处理)
创建仓库层,封装接口调用逻辑,统一校验响应体、统一处理业务异常 ,给 ViewModel 提供干净的业务方法(ViewModel 无需关注响应体解析)。
kotlin
// 网络仓库:封装所有接口调用逻辑
class NetRepository {
// 获取Retrofit接口服务(和你之前的ApiServiceFactory一致)
private val userApi = ApiServiceFactory.createUserApi()
// 登录业务方法:挂起函数,供ViewModel调用
suspend fun login(username: String, password: String): User {
// 调用Retrofit挂起函数,执行网络请求
val response = userApi.login(LoginRequest(username, password))
// 统一响应体校验(和你之前的RxTransformer逻辑一致)
if (response.isSuccess()) {
// 成功:返回业务数据,若数据为空则抛出业务异常
return response.data ?: throw BusinessException("用户数据为空")
} else {
// 失败:抛出业务异常(携带错误码和错误信息)
throw BusinessException(response.code, response.message)
}
}
// 自定义业务异常(替代你之前的NetException)
class BusinessException(val code: Int = -1, msg: String) : Exception(msg)
}
步骤 3:ViewModel 层调用(协程版,核心)
通过viewModelScope启动协程,调用仓库的挂起函数,用withContext指定 IO 线程,用try/catch统一处理所有异常(网络异常 / 业务异常 / 解析异常),代码比 RxJava3 更直观。
kotlin
class UserViewModel : ViewModel() {
// 仓库实例
private val repository = NetRepository()
// 用LiveData传递数据给View层(也可用StateFlow,协程推荐)
private val _userLiveData = MutableLiveData<User?>()
val userLiveData: LiveData<User?> = _userLiveData
// 用LiveData传递异常信息
private val _errorLiveData = MutableLiveData<String>()
val errorLiveData: LiveData<String> = _errorLiveData
// 登录方法:供View层调用
fun login(username: String, password: String) {
viewModelScope.launch {
try {
// IO线程执行登录请求(withContext切换线程)
val user = withContext(Dispatchers.IO) {
repository.login(username, password)
}
// 主线程更新LiveData,View层观察更新UI
_userLiveData.value = user
} catch (e: ConnectException) {
// 网络连接异常
_errorLiveData.value = "请检查网络连接"
} catch (e: SocketTimeoutException) {
// 网络超时异常
_errorLiveData.value = "网络请求超时,请稍后重试"
} catch (e: NetRepository.BusinessException) {
// 业务异常(如Token过期/参数错误)
_errorLiveData.value = e.message ?: "请求失败"
} catch (e: Exception) {
// 未知异常
_errorLiveData.value = "未知错误,请稍后重试"
}
}
}
}
步骤 4:View 层(Activity)观察数据(无协程代码)
View 层只需观察 ViewModel 的 LiveData/StateFlow ,更新 UI 即可,无需写任何协程代码 ,符合 MVVM 的职责划分(View 层只做 UI 渲染,不处理业务逻辑)。
kotlin
class LoginActivity : AppCompatActivity() {
private val userViewModel by viewModels<UserViewModel>()
private lateinit var binding: ActivityLoginBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLoginBinding.inflate(getLayoutInflater())
setContentView(binding.root)
// 观察用户数据(登录成功)
userViewModel.userLiveData.observe(this) { user ->
user?.let {
// 更新UI:如跳转到主页面
Toast.makeText(this, "登录成功,欢迎${it.name}", Toast.LENGTH_SHORT).show()
startActivity(Intent(this, MainActivity::class.java))
finish()
}
}
// 观察异常信息(登录失败)
userViewModel.errorLiveData.observe(this) { errorMsg ->
// 显示异常提示
Toast.makeText(this, errorMsg, Toast.LENGTH_SHORT).show()
}
// 登录按钮点击事件
binding.btnLogin.setOnClickListener {
val username = binding.etUsername.text.toString().trim()
val password = binding.etPassword.text.toString().trim()
// 直接调用ViewModel方法,无需关注协程
userViewModel.login(username, password)
}
}
}
六、异常处理:Android 协程的统一方案
协程的异常处理遵循 **「作用域原则」,Android 开发中 仅需掌握两种方式 **,即可覆盖所有场景,且比 RxJava3 的异常处理更简洁。
1. 局部异常处理:try/catch(推荐,Android 最常用)
在协程执行体中直接用try/catch捕获异常,这是 Android 协程的标准异常处理方式 ,适合单个协程的异常处理(如网络请求 / 数据库操作),也是你之前在 ViewModel 中看到的方式。
kotlin
viewModelScope.launch {
try {
val data = withContext(Dispatchers.IO) { repository.getData() }
_dataLiveData.value = data
} catch (e: ConnectException) {
// 网络异常
_errorLiveData.value = "无网络"
} catch (e: BusinessException) {
// 业务异常
_errorLiveData.value = e.message
} catch (e: Exception) {
// 兜底处理所有异常
_errorLiveData.value = "未知错误"
}
}
2. 全局异常处理:CoroutineExceptionHandler(批量处理)
若需要为某个作用域下的所有协程统一处理异常 (如全局网络异常提示),可使用CoroutineExceptionHandler,适合批量协程的异常处理。
kotlin
// 1. 创建全局异常处理器
val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
// 全局处理异常(如弹全局Toast/埋点统计)
runOnUiThread {
Toast.makeText(applicationContext, "全局异常:${throwable.message}", Toast.LENGTH_SHORT).show()
}
}
// 2. 启动协程时绑定异常处理器
viewModelScope.launch(coroutineExceptionHandler) {
val data = withContext(Dispatchers.IO) { repository.getData() }
_dataLiveData.value = data
}
- 注意 :
CoroutineExceptionHandler仅能捕获未被局部try/catch捕获的异常 ,若局部已用try/catch,全局处理器不会触发。
七、避坑要点:Android 协程的 8 个常见错误(必看)
1. 不要手动创建CoroutineScope
Android 开发无需手动创建CoroutineScope ,直接使用官方内置的viewModelScope/lifecycleScope即可,手动创建易导致内存泄漏(忘记取消协程)。
2. 不要在非协程中调用挂起函数
挂起函数仅能在协程中或其他挂起函数中调用,普通函数直接调用会报编译错误,解决方式:在作用域中启动协程,再调用挂起函数。
3. 不要用Thread.sleep,必须用delay
Thread.sleep会阻塞线程 ,导致线程无法处理其他协程,协程中必须用delay(非阻塞)。
4. 不要在Dispatchers.Main中执行耗时操作
Dispatchers.Main是主线程,执行耗时操作会导致 ANR ,耗时操作必须放在Dispatchers.IO/Dispatchers.Default中。
5. 不要忽略协程的异常
协程中未被捕获的异常会导致应用崩溃 ,必须用try/catch或CoroutineExceptionHandler捕获所有异常。
6. 不要在launch中直接嵌套launch
如需嵌套协程,直接在协程执行体中写代码即可,无需嵌套launch,嵌套launch会导致协程管理混乱。
7. 网络请求不要用lifecycleScope
lifecycleScope受 Activity 重建影响,网络请求建议用viewModelScope(生命周期更长,不受页面重建影响)。
8. 不要忘记withContext的调度器
在viewModelScope/lifecycleScope中执行耗时操作时,必须用withContext(Dispatchers.IO)切换到子线程,否则会在主线程执行耗时操作,导致 ANR。
八、与 RxJava3 的对比(为什么协程是未来)
你之前用 RxJava3 搭建了响应式框架,协程作为 Android 官方推荐的方案,对比 RxJava3 有以下核心优势,也是目前生产环境逐步替换 RxJava3的原因:
| 特性 | 协程 | RxJava3 |
|---|---|---|
| 语法简洁 | 极简,一行代码启动协程,无需复杂的适配器 / 转换器 | 繁琐,需要创建 Observable/Observer,配置线程切换 / 背压 |
| 内存泄漏 | 内置作用域自动绑定生命周期,从根本上解决 | 需要手动绑定生命周期(RxLifecycle/AutoDispose),易遗漏 |
| 线程切换 | 一行withContext实现,直观高效 |
需要subscribeOn/observeOn,易混淆 |
| 异常处理 | 原生try/catch,符合 Java/Kotlin 开发习惯 |
需用onError,异常链复杂,不易调试 |
| 学习成本 | 低,基于 Kotlin 语法,3 个核心概念即可上手 | 高,背压 / 操作符 / 线程调度等概念繁多,学习曲线陡峭 |
| 官方支持 | Android 官方唯一推荐,与 Jetpack 深度集成 | 第三方库,无官方支持 |
| 性能 | 无额外开销,挂起 / 恢复是语法层面的操作 | 有额外开销,需要创建大量的 Observable/Observer 对象 |
总结
Android 中使用协程的核心精髓 可总结为3 句话,掌握后即可覆盖 99% 的开发场景:
- 作用域用内置 :直接使用
viewModelScope(MVVM 首选)/lifecycleScope,无需手动创建,生命周期自动绑定,解决内存泄漏; - 线程切换用
withContext:Dispatchers.IO执行耗时操作,Dispatchers.Main更新 UI,一行代码实现,直观高效; - 异步操作用挂起函数 :对接 Retrofit3/ROOM 等第三方库的挂起函数,协程中直接调用,原生
try/catch处理异常。
协程是 Android 异步编程的未来 ,与 Jetpack(ViewModel/LiveData/StateFlow)深度集成,也是目前大厂 Android 开发的标准方案,替换 RxJava3 后,代码会更简洁、更易维护、更不易出 bug。