Android Kotlin协同程序启动{}vs启动{withContext{}

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() } 块内的每一行都有一条警告:“不适当的块方法调用” 在搜索了

我的Android应用程序需要在后台(在服务内部)执行一些文件读/写操作,首先我使用:

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()
}
此外,你的声明:

所以基本上大多数协同程序只有一个线程,若它被阻塞,那个么该协同程序将并没有线程来做其他工作

是误导性的。协同程序没有线程,调度程序有。有些调度程序有很多线程