1. 添加 KTX 依赖
为了让 Kotlin 协程与架构组件一起使用,我们需要在项目中添加以下依赖:
// ViewModelScope
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
// LifecycleScope
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
// liveData
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
通过这些依赖,我们可以方便地将协程与 ViewModel、Lifecycle 和 LiveData 等组件结合使用,使得异步任务管理更加高效。
2. viewModelScope
2.1 老方式在 ViewModel 中使用协程
在使用 viewModelScope
之前,通常我们需要手动管理 CoroutineScope
,并在 onCleared()
方法中取消协程任务。这种方式容易出错,忘记取消协程可能会导致内存泄漏等问题。
class JetpackCoroutineViewModel : ViewModel() {
private val viewModelJob = SupervisorJob()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
fun launchDataByOldWay() {
uiScope.launch {
val result = getNetData()
log(result)
}
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
private suspend fun getNetData() = withContext(Dispatchers.IO) {
delay(1000)
"{}"
}
}
上面这种方法需要手动管理协程的生命周期,且容易遗漏取消操作。
2.2 新方式在 ViewModel 中使用协程
现在,使用 viewModelScope
,我们可以简化协程的使用。viewModelScope
会在 ViewModel 被销毁时自动取消协程,减少了很多样板代码。
class JetpackCoroutineViewModel : ViewModel() {
fun launchData() {
viewModelScope.launch {
val result = getNetData()
log(result)
}
}
private suspend fun getNetData() = withContext(Dispatchers.IO) {
delay(1000)
"{}"
}
}
不再需要手动管理协程,协程的生命周期由 viewModelScope
管理,自动与 ViewModel 的生命周期挂钩。
2.3 viewModelScope 的底层实现
viewModelScope
实际上是 ViewModel
的一个扩展属性,它返回一个 CoroutineScope
,该作用域在 ViewModel 被销毁时会自动取消。
public val ViewModel.viewModelScope: CoroutineScope
get() {
val scope: CoroutineScope? = this.getTag(JOB_KEY)
if (scope != null) {
return scope
}
return setTagIfAbsent(
JOB_KEY,
CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
)
}
viewModelScope
使用了 CloseableCoroutineScope
,这个作用域会在 ViewModel 被销毁时自动取消协程。
3. lifecycleScope
lifecycleScope
是一个与 Lifecycle
绑定的协程作用域,它会在组件的生命周期结束时自动取消协程,确保协程不会在不再需要时继续执行。
3.1 使用 lifecycleScope
例如,我们可以在 Activity 的 onCreate
中使用 lifecycleScope
来执行协程任务,并在 onDestroy
时自动取消:
lifecycleScope.launch {
repeat(100000) {
delay(100)
tvText.text = "$it"
}
}
通过 lifecycleScope
,我们不再需要手动管理协程的生命周期,它会根据 Activity 或 Fragment 的生命周期自动管理协程的启动和取消。
3.2 lifecycleScope 的底层实现
lifecycleScope
是 LifecycleOwner
的扩展属性,返回一个 LifecycleCoroutineScope
,并会根据生命周期状态自动管理协程的取消。
val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
get() = lifecycle.coroutineScope
LifecycleCoroutineScope
会在生命周期结束时取消协程,避免协程在不再需要时继续执行。
4. liveData
LiveData
是 Android 中用于管理 UI 相关数据的组件,结合 Kotlin 协程后,可以更加简洁地处理异步数据流。
4.1 liveData 的使用
通过 liveData
构造器,我们可以轻松在协程中加载数据并将其暴露为 LiveData:
val netData: LiveData<String> = liveData {
val data = getNetData()
emit(data)
}
private suspend fun getNetData() = withContext(Dispatchers.IO) {
delay(5000)
"{}"
}
liveData
构造器会自动在协程作用域中执行,并且数据会通过 emit
函数发送出去。当组件处于活动状态时,LiveData
会更新数据。
4.2 liveData 的底层实现
liveData
是一个全局函数,返回一个 CoroutineLiveData
对象。在这个对象中,协程任务会在内部启动,并通过 emit
更新 LiveData
的值。
fun <T> liveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
block: suspend LiveDataScope<T>.() -> Unit
): LiveData<T> = CoroutineLiveData(context, timeoutInMs, block)
CoroutineLiveData
继承自 MediatorLiveData
,并且通过 BlockRunner
来执行异步任务,将结果更新到 LiveData
中。
5. 小结
Kotlin 协程和架构组件的结合使用极大简化了 Android 开发中的异步任务处理。通过 viewModelScope
、lifecycleScope
和 liveData
,我们可以更方便地处理协程的生命周期管理、UI 更新和数据流。
- viewModelScope 自动管理协程,避免了手动取消的麻烦。
- lifecycleScope 根据生命周期自动取消协程,防止内存泄漏。
- liveData 在协程中处理异步数据流,简化 UI 数据绑定。
通过这些扩展和 API,协程与架构组件的结合提供了更加简洁、安全的异步编程方式,极大地提升了开发效率和代码质量。
🌟 关注我的优快云博客,收获更多技术干货! 🌟