本文介绍了在某些情况下(单件)可以从Android上的Globalscope启动协程吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Activity,Fragments或Android体系结构组件ViewModel启动协程时,为了避免泄漏和释放资源,例如,使用绑定到该视图组件生命周期的协程范围是完全有意义的.用户离开屏幕时取消网络请求.

When launching coroutines from Activities, Fragments or Android Architecture Components ViewModels, it makes total sense to use a coroutine scope that is bound to the lifecycle of that view component in order to avoid leaks and free resources by e.g. canceling the network request when the user leaves the screen.

但是在其他情况下,您甚至在用户离开屏幕时也不想取消协程,例如您正在执行网络分析请求或写入数据库时​​.在这种情况下可以用GlobalScope启动协程吗?启动这些协程的对象大多是Singletons,因此它们在应用程序的整个生命周期中都存在,因此没有泄漏的危险,对吧?

But there are other situations, where you don't want to cancel a coroutine even when the user leaves the screen like when you are performing a network request for analytics or writing into a database. Is it OK to launch coroutines with GlobalScope in such situations? The objects where these coroutines are launched are mostly Singletons, so they live for the lifetime of the application anyway, so there is no danger of leaks, right?

Kotlin文档在GlobalScope上非常清楚:

The Kotlin docs are pretty clear on GlobalScope:

在这些情况下可以使用GlobalScope吗?如果没有,我的应用程序定义的CoroutineScope应该是什么样?

Is it OK to use GlobalScope in these situations? If not, how should my application-defined CoroutineScope look like?

推荐答案

如果您有一个异步工作器,其生命周期是真正全局的(它们仅在进程终止时终止/终止),请使用或类似的终身适用范围.

If you have an asynchronous worker whose lifecycles is truly global (they only die/end when your process dies), using GlobalScope or a similar life-long scope, is fine.

说,您有一个发出请求的活动,但是即使活动消失了,实际的网络请求也需要继续,因为您想在网络最终返回响应时对其进行缓存.

Say, you have an Activity that makes a request, but the actual network-request needs to continue even if the Activity goes away, because you'd like to cache it when the network finally returns a response.

您将在中添加CoroutineScope,或者在ViewModel中添加更好,并使最终将内容放到屏幕上的代码在该范围内运行.当Activity/Fragment/ViewModel死亡时,范围将被取消,并且将不会尝试在不再存在的屏幕上显示任何内容.

You'll add a CoroutineScope to your Activity/Fragment, or better to your ViewModel and have your code that finally puts stuff on the screen run in that scope. When the Activity/Fragment/ViewModel dies, the scope is canceled and nothing will be attempted to show something on a screen that no longer exists.

但是,您的Fragment/Activity/ViewModel可能会与生命周期仅在进程终止时才结束的数据源/存储库进行通信.您可以在其中切换到GlobalScope ,以便即使没有活动的"Activation/Fragment/ViewModel"在屏幕上显示结果,也可以缓存您的网络响应.

However, your Fragment/Activity/ViewModel may talk to a data-source/repository that has a lifecycle that only ends when the process dies. You can switch to a GlobalScope in there so that your network-responses get cached, even when no Activity/Fragment/ViewModel is alive to show the result on the screen.

class MyViewModel(context: CoroutineContext, repo: MyRepository) : ViewModel() {
    private val scope = CoroutineScope(context + SuperviserJob())

    override fun onCleared() { scope.cancel() }

    fun getDataFromNetwork() {
        scope.launch {
            myLiveData.value = repo.getDataFromNetwork()
        }
    }

}

// Singleton class
class MyRepositoryImpl(context: CoroutineContext) : MyRepository {
    private val scope = CoroutineScope(context + SupervisorJob())

    override suspend fun getDataFromNetwork() : String {
        return scope.async { // switch scopes
            val data = ... fetch data ...
            saveInCache(data)
        }.await()
    }
}

当ViewModel结束(调用onCleared)时,MyRepositoryImplgetDataFromNetwork仍保持运行,如果一切正常,将调用saveInCache.但是,返回的值不会分配给myLiveData.value,因为ViewModel范围的协程已取消.

When your ViewModel ends (onCleared is called), the MyRepositoryImpl's getDataFromNetwork still keeps running and will call saveInCache if all goes right. However, the value returned won't be assigned to myLiveData.value because the coroutine of your ViewModel's scope was cancelled.

这篇关于在某些情况下(单件)可以从Android上的Globalscope启动协程吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 08:04