我正在阅读和学习Kotlin中的协同程序,以便在小型库中用于娱乐/学习目的。在文档中,您可以执行类似的操作
GlobalScope.launch {
}
所以在我的方法中,
fun myMethod() {
GlobalScope.launch {
// do some networking code
}
}
使用GlobalScope
为库启动协程是最佳做法吗?在文档中说
应用程序代码通常应该使用应用程序定义的CoroutineScope,非常不鼓励使用异步或在GlobalScope实例上启动。
这显然是一个库,不一定是应用程序代码。但我不确定这是否是与协同程序在后台进行联网的最佳方式。
我也试过了
runBlocking {
async {
// do some networking code
}
}
认为runBlocking
引入了一个新的协程范围,但我认为在这种情况下它继承了它的父节点作为主线程的范围,所以我得到一个关于主UI线程没有网络的例外。
您可以创建一个挂起函数,这将强制用户从协程本身调用它。如果您的方法使用withContext
,则不必担心GlobalScope
或配置范围。 withContext
只是告诉协程使用哪个上下文(对于网络,你需要IO
。而且范围现在由用户启动它来确定。
我构建你的方法的方式是:
suspend fun myMethod() = withContext(Dispatchers.IO) {
// do some networking code
}
根据您要实现的目标,您甚至可以在库中使用不同的模式。
如果你的函数应该在启动一些协同程序后立即返回,那么“最佳实践”是将你的函数声明为CoroutineScope
的扩展,这样你就不必使用全局作用域:
fun CoroutineScope.launchesAndReturnsImmediately() {
// launch can be called because we are extending CoroutineScope
launch {
// some work
}
}
话虽如此,您通常不需要在库中立即返回,因此您可以声明您的函数suspend
,这在消费者方面更容易掌握。那里有多种选择:
withContext
在适当的线程池上运行,或调用其他挂起函数,在后台进行一些工作coroutineScope
启动子协同程序并分解工作,但仍然暂停,直到所有子协程都完成suspendCoroutine
或suspendCancellableCoroutine
包装基于回调的异步代码来“创建”暂停