![](/img/trans.png)
[英]How to get String as a return value from "GlobalScope.launch" block
[英]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
被调用), MyRepositoryImpl
的getDataFromNetwork
仍然保持运行,如果一切顺利,将调用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.