美文网首页Corouti...
Kotlin—Coroutine(协程)的基本使用

Kotlin—Coroutine(协程)的基本使用

作者: 烫烫琨烫烫烫烫琨烫烫 | 来源:发表于2019-08-12 22:11 被阅读0次

    Kotlin—Coroutine(协程)的基本使用

    什么是协程

    在java中异步都会使用到线程,在kotlin中引入了协程的概念。与线程类似,协程也是用于处理异步的,不过与线程相比更加轻巧。协程完全通过编译技术实现,使用挂起机制来实现异步,而不会阻塞线程。协程是一种避免线程阻塞、开销更小且更加可控的异步操作

    协程的基础使用

    创建协程,有三种方式runBlockinglaunchasync

    • runBlocking 创建一个阻塞的协程,当协程内部代码执行完毕后才会执行后面的代码。

      fun main() {
          println("Hello")
          runBlocking {
              delay(1000)
              println("World")
          }
          println("---end---")
      }
      

      runBlocking 创建的协程里面,调用 delay让此协程挂起1秒。执行代码,首先打印Hello,1秒后打印World,最后打印—end—。注意delay挂起函数只有在协程内部才能调用

    • launch 在当前协程作用域下面创建一个非阻塞子协程,同时返回个 Job 对象,用来控制当前协程。

      fun main() = runBlocking {
          println("hello")
          launch {
              delay(1000)
              println("world")
          }
          println("---end---")
      }
      

      使用 runBlocking 来包裹 main 函数,函数整体都处于runBlocking创建的协程作用域下面,然后通过launch 创建一个子协程,挂起1秒之后打印输出。执行代码发现首先输出hello和—end—,等待一秒之后打印world,如何让他按顺序执行。

      fun main() = runBlocking {
          println("hello")
          val job = launch {
              delay(1000)
              println("world")
          }
          job.join()
          println("---end---")
      }
      

      修改代码,拿到 launch 返回的job对象,调用 join() 函数,此时会等待job协程内部的代码执行完毕后才会往后执行。执行代码,先打印hello,然后1秒后打印world和—end—。

    • Job 常用方法

      • isActive
      • isCompleted
      • isCanceledstart
      • cancel
      • join
    • GlobalScope.launch 创建一个全局非阻塞协程,

      fun main() {
          println("hello")
          GlobalScope.launch {
                delay(1000)
              println("world")
          }
          Thread.sleep(1500)
          println("---end---")
      }
      

      使用 GlobalScope.launch 在任何地方都能创建一个全局的协程,由于 launch 创建的协程是非阻塞的,所以让当前线程睡眠1.5秒等待协程执行完毕。与上面代码打印结果一样。由于使用 GlobalScope.launch 时,会创建一个顶层协程。虽然很轻量,但它运行时仍会消耗一些内存资源,所以通常是在协程内部作用域下使用launch创建协程,而不是使用GlobalScope来创建全局协程。

    • async 创建一个非阻塞协程,同时返回Deferred ,可通过 await() 函数获取协程返回的具体值;

      fun main() = runBlocking {
          println("hello")
          val def = async {
              delay(1000)
              "world"
          }
          println(def.await())
          println("---end---")
      }
      
    • 挂起函数

      接着上面例子,将 launch 协程内部的代码封装为一个函数,使用suspend关键,这个函数就叫 挂起函数,上面的 delay 就是一个封装好的挂起函数。

      fun main() = runBlocking {
          println("hello")
          val job = launch {
              delay1000()
          }
          job.join()
          println("---end---")
      }
      
       suspend fun delay1000(){
          delay(1000)
          println("world")
      }
      
    • 调度器

      上面提到三种创建协程的方式都有一个选填参数 CoroutineContext,协程的上下文环境。也就是协程调度器,调度器确定了协程执行的线程环境。

      • Dispatchers.Default 默认后台线程池里的线程 ;
      • Dispatchers.Main Android主线程;
      • Dispatchers.IO 后台线程池里的IO线程 ;
      • Dispatchers.Unconfined 不限制,使用父协程所属的线程;
      • newSingleThreadContext 使用新的线程。

      如需要在协程中切换调度器可使用withContextwithContext返回最后一行代码的返回值。

    • Android中的使用

      简单了介绍了协程的基本使用,写个小demo,模拟网络请求然后再界面展示数据。在activity中首先要实现CoroutineScope 接口,然后通过by关键字将接口的具体实现委托给 MainScope,这样当前activity就是一个协程作用域了。

      class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
              button.setOnClickListener {
                  showData()
              }
          }
        // 创建协程,默认在当前线程,也就是UI线程
          private fun showData() = launch {
              progress.visibility = View.VISIBLE
              textView.text = loadData()
              progress.visibility = View.GONE
          }
      
        //网络请求 切换为IO线程
          private suspend fun loadData()= withContext(Dispatchers.IO) {
              delay(2000)//挂起2秒 模拟网络请求
              "假装这是网络请求到的数据" //返回请求到的数据
          }
      }
      

    基本介绍完了协程的最最最基础的使用,相比于线程除了内存开销更小、不会造成线程阻塞的优点之外之外,个人觉得在没有用RxJava的情况下可以少写很多线程的创建、切换、异步接口的回调。让代码更加干净清爽。
    个人学习笔记,如有错误不对的地方欢迎各位大佬指出。

    相关文章

      网友评论

        本文标题:Kotlin—Coroutine(协程)的基本使用

        本文链接:https://www.haomeiwen.com/subject/vkopjctx.html