我在这里https://developer.android.com/topic/libraries/architecture/coroutines阅读如何使用协程。使我感到困惑的是LiveDataScope
和ViewModelScope
之间的区别。听起来ViewModelScope
会自动处理生命周期,您可以在该块中进行网络请求。从服务器收到数据后,将该值发布到livedata
。但是当我继续阅读时,还有一个关于LiveDataScope
的话题对我来说似乎是多余的,因为您可以通过将ViewModelScope
与livedata
一起使用来完成相同的结果。两者之间的主要区别是什么?我什么时候应该选择一个使用?
答案 0 :(得分:4)
注意:如果 OP的作者已经对此有所了解,那么这可能是该主题的较晚答案,但为@IgorGanapolsky的引用注释提供了一些指针。 / p>
让我们看看viewModelScope和LiveDataScope之间的主要区别是什么
官方文档说,
CoroutineScope
与此ViewModel
相关。这个 清除ViewModel
时,范围将被取消,即ViewModel.onCleared
被称为
这意味着协程范围与ViewModel绑定,一旦清除ViewModel,该范围将通过取消所有子协程作业而被破坏。
基本上,在MVVM模式中,我们使用ViewModel
绑定到特定的Activity/Fragment
。因此,一旦Activity/Fragment
被销毁,其ViewModel
就会达到清除状态。因此,它将取消所有以viewModelScope
开始的未完成作业,并抛出CancellationException
。
因此,viewModelScope
的用例是:在ViewModel
内,当您需要调用任何暂挂函数并且需要CoroutineScope
时,您可以直接从 viewodel-ktx 库中直接使用该新版本。
class SomeViewModel: ViewModel() {
fun someFunction() {
viewModelScope.launch {
callingSomeSuspendedFun()
callingAnotherSuspendedFun()
}
}
}
请注意,您无需显式覆盖onCleared()
的{{1}}方法即可取消范围,它会自动为您加油!
现在说到ViewModel
,它实际上是一个为更好地支持LiveDataScope
而提供的接口,可以使LiveData/CoroutineLiveData
开箱即用!使用 livedata-ktx 版本
现在设想一种情况,您正在使用MVVM模式,并且想要从存储库返回CoroutineScope
来查看模型。您的存储库还包含一些暂停的功能和一些协程范围。
在这种情况下,当您执行一些挂起的方法调用并将结果作为实时数据返回时,将需要做一些额外的工作。得到结果后,您需要将数据转换为特定的实时数据。参见下面的示例:
LiveData
想象一下,由于class SomeRepository {
suspended fun someApiCall() : LiveData<Result> {
val result = MutableLiveData<Result>()
someCoroutineScope.launch {
val someData = someOtherCallToGetResult()
result.postValue(someData)
}
return result
}
}
对协程没有任何支持,您不得不编写以上代码块... 但是直到现在!
现在,您可以直接使用LiveData
函数,该函数将返回liveData { }
对象,从而为您提供LiveData
的作用域,使您可以继续进行暂停的工作并同时发出结果水平,而不是像上面那样混乱。因此,上面的代码块现在可以通过以下代码或更好的代码进行优化:
LiveDataScope
因此,如果您从存储库向视图模型公开LiveData而不是创建新的内部viewmodel,则在使用MVVM模式时liveData的用例将处于存储库级别。请注意,没有class SomeRepository {
suspended fun someApiCall() : LiveData<Result> {
return liveData<Result> {
val someData = someOtherCallToGetResult()
emit(someData)
}
}
}
方法的经验法则不应直接在viewmodel中使用。如果您想完全避免使用liveData
,则可以。
签出liveData方法,
Doc指出,
viewModelScope
构建块用作 协程和liveData
之间的结构化并发原语。当LiveData
变为 活动,并在可配置的超时后自动取消LiveData
无效。如果在完成前被取消, 如果LiveData
重新变为活动状态,它将重新启动。如果它 在上一次运行中成功完成,它不会重新启动。注意 仅在自动取消后才重新启动。如果块是 由于其他任何原因而被取消(例如,抛出LiveData
),它不会重新启动。
我希望这有道理!
答案 1 :(得分:0)
名称暗示它们的实际含义:
为应用程序中的每个ViewModel定义了一个ViewModelScope。任何 如果在此范围内启动的协程会自动取消 ViewModel已清除。
这意味着您可以在ViewModel范围内的协程中执行某些任务(例如连续处理)。优点是您不再需要在何时停止ViewModel来停止协程(这在处理诸如Java线程之类的全局事务时会很痛苦)。 ViewModel的生命周期与结束活动的时间有关。
LiveDataScope
用于发出LiveData
对象范围内的值。这意味着只要LiveData
对象处于活动状态,并且有一些协程将正常工作的订户,但是一旦所有订户退出,协程将停止。一旦LiveData
再次处于活动状态,此协程也会重新启动。
基本上,这是2个协程上下文,每个上下文都负责其元素的生命周期。
PS:
听起来好像ViewModelScope自动照顾了生命周期 您可以在该区块中进行网络请求。
首先,无法从Main线程完成网络请求,通常是在IO范围内进行,您可以阅读more here。第二件事是,如果您想了解LiveDataScope
通常与ViewModelScope
结合的原因,那么应该查看一下ViewModel与Activity相比的生命周期,您可以了解有关here的信息。 。
这个问题的简短答案是,您不能确定是否从ViewModelScope
创建视图,因此,如果要将某些更新推送到UI,只要有人订阅了LiveData,就应该推送这些更新,这就是LiveDataScope
发挥作用的地方。