【问题标题】:Kotlin coroutines: why is this not throwing a NetworkOnMainThreadException?Kotlin 协程:为什么不抛出 NetworkOnMainThreadException?
【发布时间】:2019-03-18 14:30:12
【问题描述】:

client 使用 Retrofit Coroutines Adapter。

我不明白,为什么我没有收到NetworkOnMainThreadException?? 它不是在主线程上调用的吗?

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val deferred = client.getStuffDeferred(file)
    CoroutineScope(Dispatchers.Main).launch {
        val response = deferred.await()
    }
}

【问题讨论】:

  • 你的问题标题说代码正在抛出NetworkOnMainThreadException。您的问题正文说代码抛出NetworkOnMainThreadException。是哪个?
  • 而不是Dispatchers.Main 使用任何其他线程。 (即Dispatchers.Default
  • 好的。在 Dispatcher.Main [UI 线程] 中启动协程不会抛出此异常,因为它会启动一个子协程,就像主线程中的线程一样,不会阻塞主线程操作。但最好在执行网络调用时使用 withContext(Dispatcher.IO) @lisa-anne
  • 为什么?同理new AsyncTask(){...}.get();不会抛出

标签: android kotlin kotlin-coroutines


【解决方案1】:

如果您将 Coroutine Context 传递给您的协程构建器,那么这样的协程将使用该线程来执行。

  1. Dispatchers.Default – 如果在上下文中没有指定调度程序或任何其他 ContinuationInterceptor,则所有标准构建器都使用它。它使用共享后台线程的公共池。对于消耗 CPU 资源的计算密集型协程来说,这是一个合适的选择。
  2. Dispatchers.IO – 使用按需创建的线程共享池,旨在卸载 IO 密集型阻塞操作(如文件 I/O 和阻塞套接字 I/O)。
  3. Dispatchers.Unconfined – 在当前调用帧中开始协程执行,直到第一次暂停。在第一次暂停时,协程构建器函数返回。协程在相应挂起函数使用的任何线程中恢复,而不将其限制在任何特定线程或池中。通常不应在代码中使用无约束调度程序。
  4. 可以使用newSingleThreadContextnewFixedThreadPoolContext 创建私有线程池。
  5. 任意Executor 都可以通过asCoroutineDispatcher 扩展函数转换为调度程序。

所以,像这样使用:

CoroutineScope(Dispatchers.IO).launch { // we should use IO thread here !

}

【讨论】:

    【解决方案2】:

    如果您在 Dispatchers.Main 上调用 launch,它会在主线程上运行,但会暂停执行以免阻塞线程。

    所以这种行为不会阻塞或抛出 NetworkOnMainThreadException,因为您的 CoroutineScope 中没有挂起方法或 runBlocking 方法

    但是: 您应该在进行网络操作或任何繁重的操作期间更改您的上下文,使用可能会减慢您的 UI 线程操作

    withContext(Dispatchers.IO){// your suspended calls}
    

    它允许您将当前上下文更改为后台线程并在主线程中继续工作而不会出现任何问题

    在解决方案 3 上查看此 article 其中使用协程

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      相关资源
      最近更新 更多