如何计划Kotlin协同程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何计划Kotlin协同程序相关的知识,希望对你有一定的参考价值。

我最近一直在阅读很多文章并观看很多关于Kotlin合作的视频,尽管我付出了努力,但我还是无法理解它们。

我想我终于找到了一种方法来说明我的问题:

class MyViewModel() : CoroutineScope {

override val coroutineContext = Dispatchers.Main + Job()

    fun foo() = launch(handler) {
        Log.e("test", "A")
    }
}

class MainActivity : Activity() {
    override fun onCreate() {
        MainViewModel().foo()
        Log.e("test", "B")
    }
}

这个输出是:

E/test: B
E/test: A

我不明白这是怎么回事,我只使用一个线程(主线程)。如果我的代码按顺序执行,那么当我到达行log(B)时... log(A)应该已经打印出来了。

协同程序库是否在内部使用其他线程来完成此任务?这是我能提出的唯一解释,但在文档中没有找到任何说法。

PS:很抱歉把android扔进了混合但是这段代码:

fun main() {
    GlobalScope.launch(Dispatchers.Unconfined) { // launch new coroutine in background and continue
        print(Thread.currentThread().name + "World!") // print after delay
    }
    (0 .. 1000).forEach { print(".") }
}

似乎按预期工作并打印:main @coroutine#1World!...........................

因为1 thread == sequential work

希望我的问题有道理,感谢阅读!

答案

在引擎盖下,主调度程序使用Handler将Runnable发布到MessageQueue。基本上,它会被添加到事件队列的末尾。这意味着它将很快执行,但不会立即执行。因此,为什么“B”在“A”之前打印。

您可以在this article找到更多信息。

OP编辑(阅读上面的文章,然后阅读本文):

只是想澄清为什么上面的Android示例工作正常,万一有人还在想。

fun main() {
    GlobalScope.launch(Dispatchers.Unconfined) { // launch new coroutine in background and continue
        print(Thread.currentThread().name + "World!") // print after delay
    }
    (0 .. 1000).forEach { print(".") }
}

我们设置GlobalScope使用UNCONFINED调度员,这个调度员将isDispatchNeeded设置为falsefalse的意思是“在当前线程中安排”,这就是我们看到按顺序打印日志的原因。 UNCONFINED不应该用于常规代码。

所有其他调度员都将isDispatchNeeded设置为true甚至是UI调度员。见:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/is-dispatch-needed.html

(顺便说一下,如果我们没有指定一个,则GlobalScope会使用Default调度程序)

以上是关于如何计划Kotlin协同程序的主要内容,如果未能解决你的问题,请参考以下文章

在intelliJ项目中集成Kotlinx协同程序

如何在kotlin的片段内显示网格视图?

如何在kotlin中从一个片段转到另一个片段?

如何从片段 KOTLIN 中调用意图 [重复]

如何更改片段 Kotlin

kotlin:如何在两个片段之间传递数据