kotlin中CoroutineScope CoroutineContext的理解

简单来说,CoroutineScope是启动协程的作用域,所有协程都需要在作用域中启动,并且作用域内部创建子协程则会自动传播给子协程;

而CoroutineContext则是在协程作用域中执行的线程切换。

1、首先我们来看下Scope作用域的理解,示例代码:

import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() {
    runBlocking {
        val scope0 = this
        // scope0是顶级协程范围。
        scope0.launch {
            val scope1 = this
            // scope1从scope0继承其上下文。它用自己的作业替换Job字段,该作业是scope0中该作业的子级。
            // 它保留了Dispatcher字段,因此启动的协程使用runBlocking创建的调度程序。
            scope1.launch {
                val scope2 = this
                // scope2继承自scope1
            }
        }
    }
}

可以很明显的看到编译器的提示在runBlocking、scope0、scope1、scope2中均是指的同一个作用域CoroutineScope。

因此这也就解释了文章SupervisorJob使用的原因,如果里面的scope1取消掉,或者scope2在使用过程中抛出异常,

那么这整片的scope均会取消掉或者抛出异常影响到外层的scope执行,也即会影响到scope0、runblocking作用域的代码执行。

这也就是kotlin作用域的自动传播机制。

2、下面看下Context的理解,示例代码:

    runBlocking(Dispatchers.Main) {
        withContext(Dispatchers.IO) { }
        withContext(Dispatchers.Main) { }
        withContext(Dispatchers.IO) { }
        withContext(Dispatchers.Default) { }
    }

同样是使用runblocking创建的协程作用域,不同的是这里使用了带context参数的方式,在这个runblocking作用域内使用Dispatchers进行了多次的context切换,也就是线程的多次切换,其实质就是context提供了对底层线程的引用,方便我们再作用域内部进行线程的切换

再来看下CoroutineScope的源码,其实CoroutineScope内部含有CoroutineContext

public interface CoroutineScope {
    public val coroutineContext: CoroutineContext
}

综上,CoroutineScope是协程作用域,其内部本身就含有一个CoroutineContext线程,默认是主线程。在协程作用域内可以创建更多的子协程,这些协程内部是自动继承自父协程的生命周期。而CoroutineContext仅仅就是在作用域内为协程进行线程切换的快捷方式。

猜你喜欢

转载自blog.csdn.net/cpcpcp123/article/details/113348214