android - Android 中的 LiveDataScope 与 ViewModelScope

标签 android android-livedata kotlin-coroutines android-viewmodel

我在这里阅读如何使用协程 https://developer.android.com/topic/libraries/architecture/coroutines .让我感到困惑的是 LiveDataScope 之间的区别和 ViewModelScope .听起来像 ViewModelScope自动处理生命周期,您可以在 block 中进行网络请求。当从服务器收到数据时,将值发送到 livedata .但是当我继续阅读时,还有另一个关于 LiveDataScope 的话题这对我来说似乎是多余的,因为您已经可以通过使用 ViewModelScope 来完成相同的结果。与 livedata .这两者之间的主要区别是什么?我应该在什么时候选择使用一个而不是另一个?

最佳答案

注意:如果 OP 的作者 已经对此有所了解,但为@IgorGanapolsky 的引用评论提供了一些指示,这可能是该主题的迟到答案。


让我们看看 viewModelScope 之间的主要区别是什么& LiveDataScope

1。 View 模型范围:

Official doc says that, CoroutineScope tied to this ViewModel. This scope will be canceled when ViewModel will be cleared, i.e ViewModel.onCleared is called

这意味着协程作用域与 ViewModel 相关联,一旦 ViewModel 被清除,这个作用域就会通过取消所有子协程作业来销毁。

基本上,在 MVVM 模式中,我们使用绑定(bind)到特定 Activity/FragmentViewModel。因此,一旦 Activity/Fragment 被销毁,它的 ViewModel 就会达到清除状态。因此,它会取消所有viewModelScope 启动的未完成作业,并抛出 CancellationException

因此 viewModelScope 的一个用例是:在 ViewModel 中,当您有任何要调用的挂起函数并需要一个 CoroutineScope,尽管创建了一个新的,但您可以直接从 viewodel-ktx 库中开箱即用。

class SomeViewModel: ViewModel() {

    fun someFunction() {
        viewModelScope.launch {
            callingSomeSuspendedFun()
            callingAnotherSuspendedFun()
        }
    }
}

请注意,您不需要显式重写 ViewModelonCleared() 方法来取消作用域,它会自动为您完成,干杯!

2。 LiveDataScope:

现在说到LiveDataScope,其实是为了更好地支持LiveData/CoroutineLiveData而提供的接口(interface),可以开箱即用CoroutineScope !使用livedata-ktx版本

现在想象一下您有一个 MVVM 模式并希望将 LiveData 从存储库返回到 View 模型的情况。您的存储库还包含一些挂起的函数和一些协程范围。

在那种情况下,当您执行一些暂停的方法调用并将结果作为实时数据返回时,会有一些额外的工作。获得结果后,您需要将数据转换为特定的实时数据。看下面的例子:

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 的范围继续暂停的工作并在同一级别发出结果,而不是像上面那样弄得一团糟。所以上面的代码块现在可以通过以下代码或更好的代码进行优化:

class SomeRepository {

    suspended fun someApiCall() : LiveData<Result> {
        return liveData<Result> {
            val someData = someOtherCallToGetResult()
            emit(someData)
        }
    }
}

因此,如果您将 LiveData 从存储库公开到 View 模型而不是在内部创建新的 View 模型,那么在使用 MVVM 模式时,liveData 的用例将处于存储库级别。请注意,没有关于 liveData 方法不应该直接在 viewmodel 中使用的经验法则。如果你想完全避免 viewModelScope,你可以。


长话短说

查看 liveData方法,

Doc states that, The liveData building block serves as a structured concurrency primitive between coroutines and LiveData. The code block starts executing when LiveData becomes active and is automatically canceled after a configurable timeout when the LiveData becomes inactive. If it is canceled before completion, it is restarted if the LiveData becomes active again. If it completed successfully in a previous run, it doesn't restart. Note that it is restarted only if canceled automatically. If the block is canceled for any other reason (e.g. throwing a CancelationException), it is not restarted.

我希望这是有道理的!

关于android - Android 中的 LiveDataScope 与 ViewModelScope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57698932/

相关文章:

android - java.io.FileNotFoundException : output. mp4(只读文件系统)

android - Android Architecture Components如何结合来自数据库和网络的LiveData?

android - Android单元测试改造失败

kotlin - LiveData的正确实现方式

android - 将MutableLiveData传递给其他ViewModel是否有效?

kotlin - 在 Kotlin 中,术语 Coroutine 和 Continuation 有什么区别?

android - 取消 ViewModel 的 onCleared() 上的所有 Kotlin 协程挂起作业

Android环境下Java日期解析特定字符串格式

android - 如何从 android 的 setOnItemClickListener 中的 listview 获取对象?

android - 在 Android 平台上使用 Google Map Data API