kotlin协程

Posted 按劳分配

tags:

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

一、CoroutineScope 协程作用域,通过socpe启动一个或者多个协程,同一个socpe启动都算他的子协程

GlobalScope //全局协程,生命周期与app相同,调度器是默认调度器,线程池

MainScope() //在主线程启动协程 默认调度器是Main,在ui主线程调度执行

viewmodelScope //生命周期与viewmodel绑定的协程 默认调度器是Main,在ui主线程调度

private val mainScope= MainScope()

override fun initView(view: View) 
  mainScope.launch
     
    

fun destroy()
mainScope.cancel()

二、launch 和async启动协程,join和await 挂起函数,等待协程执行结束,join没有返回值,await有返回值
注意,在协程中,通过launch或者async启动子协程,进行结构化并发,子协程在launch或者async以后就启动了,在异步执行,如果要显示等待这个协议执行完,才使用join或者await

Default :协程创建后立即开始调度。在调度前如果协程被取消。将其直接进入取消相应的状态。

ATOMIC:协程创建后。立即开始调度。协程执行到第一个挂起点之前不相应取消。

LAZY:只有协程被需要时,包括主动调协程的start、join或者await等函数时,才会开始调度,如果调度前就被取消。那么该协程将直接进入异常状态。

UNDISPATCHED:协程创建后立即在当前函数调用栈中执行,直到遇到第一个真正挂起的点。

三、协程上下文 CoroutineContext 是集合,是各种不同元素的集合,+ 操作符,也就是他的plus方法,
我们可以使用 + 操作符来实现。 比如说,我们可以显式指定一个调度器来启动协程并且同时显式指定一个命名
其实就是plus方法,协程上下文是一个链表 plus方法吧这些协程上下文元素全部组合起来传入
launch(Dispatchers.Default + CoroutineName(“test”))
println(“I’m working in thread $Thread.currentThread().name”)

注意,协程取消,同一个协程作用域,也就是使用同一个协程上下文才是子协程,如果不使用同一个协程上下文启动的协程不是子协程,取消协程作用域,子协程都会取消,兄弟协程取消不会相互影响

四、coroutineScope与runBlocking的区别在于runBlocking会阻塞当前线程,而coroutineScope会挂起所在的协程直至其内部任务(包括子协程)执行完成,它不会阻塞所在的线程。
注意:coroutineScope有一个子协程异常,他的其他子协程都会取消,supervisorScope 子协程以前其他子协程不受影响
注意,如果在一个协程A中,再启动一个协程b,然后等待b协程执行完以后在执行A中后面代码,那么就可以使用coroutineScope这些挂起函数,coroutineScope会挂起所在的协程直至其内部任务(包括子协程)执行完成
例子

GlobalScope.launch  
//启动了两个子协程,在默认调度器的线程中异步执行,不会阻塞当前所在顶层协程
        launch 
                delay(1000)
                withContext(Dispatchers.Main) 
                    toast("子协程1来了")
                
            
            launch 
                delay(500)
                withContext(Dispatchers.Main) 
                    toast("子协程2来了")
                
            
//coroutineScope 是挂起函数,启动了两个子协程,会挂起顶层协程,也就是当前协程会挂起在这里,不会继续执行,需/要等待coroutineScope 内部的子协程执行完,才会继续执行
        coroutineScope 

            launch 
                delay(1000)
                withContext(Dispatchers.Main) 
                    toast("子协程1来了")
                
            
            launch 
                delay(500)
                withContext(Dispatchers.Main) 
                    toast("子协程2来了")
                
            

        

        Log.i("lmj", Thread.currentThread().name + "GlobalScope")
        withContext(Dispatchers.Main) 
            Log.i("lmj", Thread.currentThread().name + "Main")
            toast("开始了")
        
      
    

五、withContext必须在协程或者suspend函数中调用,否则会报错。它必须显示指定代码块所运行的线程,它会阻塞当前上下文线程,有返回值,会返回代码块的最后一行的值。

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

深入理解Kotlin协程协程的分类与线程的区别

深潜Koltin协程:Job 和等待子协程

Kotlin 协程基础Coroutine

Kotlin 协程基础Coroutine

Kotlin 协程基础Coroutine

Kotlin 协程基础Coroutine