[英]lifecycleScope.launch vs coroutine inside onViewCreated
[英]Kotlin Coroutine launch{} vs launch{ withContext{} }
我的 Android 应用程序需要在后台(在服务内)进行一些文件读/写,首先我使用:
CoroutineScope(Dispatchers.IO).launch {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
块内的每一行都有一个警告:“不适当的阻塞方法调用”
搜索问题后,我认为我理解了 80%。 所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。 要解决这个问题,我们应该像这样将它包装在withContext
:
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
}
Android Studio 仍然显示警告。 帖子说这只是 Android Studio 中的一个错误,这个解决方案很好。
我不明白的是, withContext
仍在Dispatchers.IO
上运行。 从launch
块来看,它可能看起来像非阻塞,但如果Dispatchers.IO
只有 1 个线程并且withContext
块在该线程上运行,那么该线程仍然被阻塞,不是吗?
我还了解到Dispatchers.IO
实际上有无限线程,它只是在需要时创建一个新线程。 所以withContext
实际上并没有阻塞,但如果这是真的,为什么我们需要withContext
块? 如果Dispatchers.IO
可以在需要时创建线程从而永远不会被阻塞,那么第一个代码不会有任何问题,对吧?
是的,这是一个带有警告的错误。 Lint 无法检测到 scope 使用的是什么 Dispatcher,我想他们只是假设您使用的是 scope,其上下文使用Dispatchers.Main
,因为这是最常见的。
您的 CoroutineScope(伪)构造函数具有Dispatchers.IO
的上下文,因此如果不修改它, launch
会继承该上下文,因此您启动的协程也使用Dispatchers.IO
。 所以,你的withContext
块是多余的。
解决方法是在启动时指定调度程序:
CoroutineScope(Job()).launch(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
另外,你的声明:
所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。
具有误导性。 协程没有线程,而 Dispatcher 有。 并且有些 Dispatcher 有很多线程。
似乎 Android Studio 中确实存在错误。 以下代码对我没有显示任何警告:
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
val fos = context.openFileOutput("", Context.MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
您还应该知道,这段代码与您共享的两段代码在行为上几乎没有区别。 在这三种情况下,代码都将在 IO 线程上执行。
CoroutineScope(context)
launch(context)
withContext(context
所有这些方法都只是指定协程上下文。 默认情况下, launch
使用协程 scope 上下文,但您可以像我上面所做的那样或使用withContext
来更改它。
所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。
Dispatchers.IO
实际上默认为 64 个线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.