在 Android 中使用 Dispatcher v/s 主线程会发生什么

What happens using a Dispatcher v/s Main Thread in Android

在 Android 的上下文中,调度程序与主线程之间的区别是什么。

根据我参考文档的理解,

It is backed by a shared pool of threads on JVM. By default, the maximal level of parallelism used by this dispatcher is equal to the number of CPU cores, but is at least two. Level of parallelism X guarantees that no more than X tasks can be executed in this dispatcher in parallel.

它会产生一个新线程还是会根据日志名称 DefaultDispatcher-worker-1 一个 worker 将与除主线程之外的线程池通信以处理协同例程块或 worker 本身是协程?

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val timeInMillis = measureTimeMillis {
            GlobalScope.launch(Dispatchers.Default) {
                Log.d(TAG, "Starting coroutine in thread ${Thread.currentThread().name}")
                val answer = doNetworkCall()
                withContext(Dispatchers.Main) {
                    Log.d(TAG, "Setting text in thread ${Thread.currentThread().name}")
                }
            }

        }
        Log.d(TAG, "(The operation took $timeInMillis ms)")

    }

Dispatcher 本质上是一个线程池。当你使用launch(Dispatchers.Default)时,用于运行协程中代码的Thread将从Dispatchers.Default获取。每次协程中有一个挂起函数调用,当协程在该调用后恢复时,它可能会在来自同一 Dispatchers.Default 线程池的不同 Thread 实例上恢复。

"DefaultDispatcher-worker-1" 是来自 Dispatcher.Default 池的文字 Thread 实例的名称。

withContext 本身就是一个挂起函数调用,因此 withContext 块之后的任何代码也将在来自 Dispatchers.Default 的某个线程上恢复。 (您的示例中有 none)。

withContext(Dispatchers.Main) 中的代码将在 Dispatchers.Main.

的线程上 运行

Dispatchers.Main 是一种特殊的 Dispatcher,它只有一个线程,并且该线程与 OS.

使用的主线程相同

你应该很少需要使用 GlobalScope 并且不鼓励使用它,因为它不允许轻松管理协程生命周期。如果您改用 lifecycleScope,当关联的 Activity 或 Fragment 关闭时,您的协程将自动取消。这通常是您想要的,因为 Activity 或片段在消失后不应该继续工作。

通常在 Android,大多数协程应该从 lifecycleScopeviewModelScope 启动,并且不需要指定 Dispatcher,因为这些范围默认使用 Dispatchers.Main这通常是你想要的。 (实际上,他们使用了一个名为 Dispatchers.Main.immediate 的不同调度程序,它也使用主线程,但也可以 运行 协程的第一部分立即执行,而不会延迟到主线程循环的下一帧。这不是区别需要担心。)您可以将需要其他调度程序的协程部分包装在 withContext 中。如果您只是调用挂起函数,则无需执行此操作。按照惯例,如果需要,可以挂起函数以在内部委托给特定的 Dispatcher。

如果您在 viewModelScope 中启动一个协程,它会执行一些阻塞工作并且从不触及任何仅主线程的东西,则上述段落可能会有一个例外。然后您可以跳过 withContext 并使用 launch.

明确指定调度程序