Android Kotlin协同程序启动{}vs启动{withContext{}
我的Android应用程序需要在后台(在服务内部)执行一些文件读/写操作,首先我使用:Android Kotlin协同程序启动{}vs启动{withContext{},android,multithreading,kotlin,kotlin-coroutines,Android,Multithreading,Kotlin,Kotlin Coroutines,我的Android应用程序需要在后台(在服务内部)执行一些文件读/写操作,首先我使用: CoroutineScope(Dispatchers.IO).launch { val fos = openFileOutput(fileName, MODE_PRIVATE) val oos = ObjectOutputStream(fos) oos.writeObject(myObj) oos.close() } 块内的每一行都有一条警告:“不适当的块方法调用” 在搜索了
CoroutineScope(Dispatchers.IO).launch {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
块内的每一行都有一条警告:“不适当的块方法调用”
在搜索了这个问题之后,我想我理解了80%。所以基本上大多数协同程序只有一个线程,若它被阻塞,那个么该协同程序将并没有线程来做其他工作。要解决此问题,我们应该将其包装在中,并使用context
如下所示:
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中的一个bug,那么这个解决方案就可以了
我不明白的是,withContext
仍然在Dispatchers.IO
上运行。从launch
块看,它可能看起来是非阻塞的,但是如果Dispatchers.IO
只有一个线程,并且withContext
块在该线程上运行,那么该线程仍然被阻塞,不是吗
我还了解到,
Dispatchers.IO实际上有无限多个线程,它只是在需要时创建一个新线程。所以withContext
实际上不是阻塞,但是如果这是真的,为什么我们需要withContext
阻塞呢?如果Dispatchers.IO可以在需要时创建线程,那么第一个代码不会有任何问题,因此永远不会被阻止,对吗?Android Studio中似乎确实存在一个bug。以下代码对我没有显示任何警告:
CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
val fos = context.openFileOutput("", Context.MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
您还应该知道,在这段代码和您共享的两段代码之间,行为几乎没有区别。在这三种情况下,代码都将在IO线程上执行
CoroutineScope(上下文)
launch(上下文)
withContext(context
所有这些方法都只是指定协同程序上下文。默认情况下,launch
使用协同程序作用域上下文,但您可以像我上面所做的那样或通过使用withContext
来更改它
所以基本上大多数协同程序只有一个线程,若它被阻塞,那个么该协同程序将并没有线程来做其他工作
Dispatchers.IO
实际上默认为64个线程。是的,这是一个带有警告的错误。Lint无法检测作用域正在使用的调度器,我想他们只是假设您使用的作用域的上下文使用了Dispatchers.Main
,因为这是最常见的
您的协同路由作用域(伪)构造函数有一个与Dispatchers.IO
的上下文,因此launch
如果不修改它,则继承该上下文,因此您启动的协同路由也使用Dispatchers.IO
。因此,您的with context
块是冗余的
解决方法是在启动时指定调度程序:
CoroutineScope(Job()).launch(Dispatchers.IO) {
val fos = openFileOutput(fileName, MODE_PRIVATE)
val oos = ObjectOutputStream(fos)
oos.writeObject(myObj)
oos.close()
}
此外,你的声明:
所以基本上大多数协同程序只有一个线程,若它被阻塞,那个么该协同程序将并没有线程来做其他工作
是误导性的。协同程序没有线程,调度程序有。有些调度程序有很多线程