繁体   English   中英

在某些情况下(单例)可以在 Android 上从 Globalscope 启动协程吗?

[英]Is it OK to launch coroutines from Globalscope on Android in certain situations (singletons)?

当从活动、片段或 Android 架构组件视图模型启动协程时,使用绑定到该视图组件生命周期的协程范围是完全有意义的,以避免泄漏和释放资源,例如在用户离开时取消网络请求屏幕。

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

在 GlobalScope 上,Kotlin 文档非常清楚:

应用程序代码通常应该使用应用程序定义的 CoroutineScope。 强烈建议不要在 GlobalScope 实例上使用 async 或 launch。

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

如果您有一个生命周期真正全局化的异步工作线程(它们只会在您的进程终止时终止/终止),那么使用GlobalScope或类似的终身作用域就可以了。

假设您有一个发出请求的 Activity,但即使 Activity 消失,实际的网络请求也需要继续,因为您希望在网络最终返回响应时缓存它。

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

但是,您的 Fragment/Activity/ViewModel 可能会与具有生命周期的数据源/存储库对话,该生命周期仅在进程终止时结束。 您可以在那里切换到 GlobalScope,以便缓存您的网络响应,即使没有活动/片段/ViewModel 处于活动状态以在屏幕上显示结果。

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 范围的协程被取消。

鉴于您已经尝试将它附加到应用程序的生命周期,我建议要么将作用域传递给您的单例,要么通过它实现一个协程作用域。 不幸的是,在 GlobalScope 上运行协程仍然可能以泄漏告终。 有关更多信息,请参阅 Roman Elizarov 的这篇精彩文章: https : //medium.com/@elizarov/the-reason-to-avoid-globalscope-835337445abc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM