前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kotlin---协程的使用

Kotlin---协程的使用

作者头像
None_Ling
发布2019-02-25 16:39:35
1.2K0
发布2019-02-25 16:39:35
举报
文章被收录于专栏:Android相关Android相关

第一个协程

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

首先来创建一个协程:

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

而打印出的结果为:

代码语言:javascript
复制
Hello,...main
World!...DefaultDispatcher-worker-1 @coroutine#1

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

  • 启动了新的线程,在该线程中创建了一个协程@coroutine#1
  • 在该协程中delay(1000L)等待了1秒后再输出日志。
  • 并且这样执行的协程,并不会阻塞主线程的执行

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

阻塞的协程runBlocking

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

代码语言:javascript
复制
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")
}

从输出结果,可以看到:

  • 直接在runBlocking中调用delay()会阻塞当前线程
  • runBlocking中调用launch()会开启新的协程,并且不会阻塞当前线程
  • runBlocking中调用launch()会在当前线程中执行协程
代码语言:javascript
复制
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函数,可以等待协程执行完毕再继续执行。

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

输出结果:

代码语言:javascript
复制
Hello,...DefaultDispatcher-worker-1 @coroutine#2
World!...main @coroutine#1

CoroutineScope作用域

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

代码语言:javascript
复制
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 ")
}

输出的结果:

代码语言:javascript
复制
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()

  • 使用suspend标示的函数只能用于协程中,无法在其他函数中被调用
代码语言:javascript
复制
import kotlinx.coroutines.*

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

// 你的第一个挂起函数
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.01.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一个协程
  • 阻塞的协程runBlocking
  • 等待协程执行完毕
  • CoroutineScope作用域
  • 挂起函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档