Kotlin---协程的使用

2019-01-09  本文已影响21人  None_Ling

第一个协程

在使用协程之前,需要保证Kotlin-Gradle-Plugin的版本高于1.3。目前最高的版本为1.3.11。否则编译会报错

首先来创建一个协程:

GlobalScope.launch { // 在后台启动一个新的协程并继续
        delay(1000L) // 非阻塞的等待 1 秒钟(默认时间单位是毫秒)
        println("World!...${Thread.currentThread().name}") // 在延迟后打印输出
}
println("Hello,...${Thread.currentThread().name}") // 协程已在等待时主线程还在继续

而打印出的结果为:

Hello,...main
World!...DefaultDispatcher-worker-1 @coroutine#1

可以看到通过GlobalScope.launch完成了:

delay函数只能在协程中使用,否则编译不过,尽量避免使用GlobalScope.launch创建协程,当我们使用 GlobalScope.launch 时,我们会创建一个顶层协程。虽然它很轻量,但它运行时仍会消耗一些内存资源。如果我们忘记保持对新启动的协程的引用,它还会继续运行。

阻塞的协程runBlocking

GlobalScope.launch启动了一个线程创建新的协程,并没有阻塞当前线程。而如果想要在当前线程创建协程的话,则需要使用runBlocking

runBlocking {
      launch {
         Log.e(TAG,"${Thread.currentThread().name}...start delay 2000L")
         delay(2000L)
         Log.e(TAG,"${Thread.currentThread().name}...delay 2000L")
       }
      launch {
          Log.e(TAG,"${Thread.currentThread().name}...start delay 4000L")
          delay(4000L)
          Log.e(TAG,"${Thread.currentThread().name}...delay 4000L")
      }
      Log.e(TAG,"${Thread.currentThread().name}...launch 2 coroutines")
}

从输出结果,可以看到:

main @coroutine#1...launch 2 coroutines
main @coroutine#2...start delay 2000L
main @coroutine#3...start delay 4000L
main @coroutine#2...delay 2000L
main @coroutine#3...delay 4000L

等待协程执行完毕

无论通过GlobalScope.launch还是runBlocking中的launch,都会返回一个Job对象。通过Job.join函数,可以等待协程执行完毕再继续执行。

val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用
    delay(1000L)
    println("Hello,...${Thread.currentThread().name}")   
}
job.join() // 等待直到子协程执行结束
println("World!...${Thread.currentThread().name}")

输出结果:

Hello,...DefaultDispatcher-worker-1 @coroutine#2
World!...main @coroutine#1

CoroutineScope作用域

runBlocking中可以定义一个coroutineScope,而该函数的作用是为在这个函数中启动的协程添加作用域,只有当作用域内的协程都执行完毕后,才会继续执行当前线程。

runBlocking {
     Log.e(TAG, "${Thread.currentThread().name}...$this...start coroutineScope")
     coroutineScope {
          launch {
             delay(4000L)
             Log.e(TAG, "${Thread.currentThread().name}...$this...start delay 4000L")
          }
          launch {
             delay(3000L)
             Log.e(TAG, "${Thread.currentThread().name}...$this...start delay 3000L")
          }
     }
     Log.e(TAG, "${Thread.currentThread().name}...$this...after launch ")
}

输出的结果:

01-09 17:03:39.972  main...BlockingCoroutine{Active}@3fc800e3...start coroutineScope
01-09 17:03:39.972  main...StandaloneCoroutine{Active}@2affbae0...start delay 3000L
01-09 17:03:42.982  main...StandaloneCoroutine{Active}@23130199...start delay 4000L
01-09 17:03:43.982  main...BlockingCoroutine{Active}@3fc800e3...after launch 

可以看到,在最后的日志打印之前,会等待coroutineScope中的协程都执行完毕后,才会继续执行

挂起函数

当协程中的代码超级多的时候,通常都会把这些代码提取到一个函数中。但是这个函数必须使用suspend标识,否则编译错误,并且无法调用协程中到函数,比如delay()

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch { doWorld() }
    println("Hello,")
}

// 你的第一个挂起函数
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}
上一篇下一篇

猜你喜欢

热点阅读