美文网首页
Kotlin协程一些概念理解

Kotlin协程一些概念理解

作者: leilifengxingmw | 来源:发表于2021-11-21 13:01 被阅读0次

协程的概念

协程就是 Kotlin 提供的一套线程封装的 API,使用协程可以让多线程之间的通信更加简单。总之一句话,协程可以简化异步编程

举个例子:在IO线程发起网络请求,在主线程更新UI。

如果使用 Retrofit +回调的方式,代码类似下面这样

private fun normalRequest() {
    apiService.getWxarticle().enqueue(object : retrofit2.Callback<WxArticleResponse> {
        override fun onFailure(call: Call<WxArticleResponse>, t: Throwable) {
            //请求失败
        }

        override fun onResponse(call: Call<WxArticleResponse>, response: retrofit2.Response<WxArticleResponse>) {
            //请求成功,更新UI
        }
    })
}

如果使用 Retrofit +协程的方式,代码类似下面这样

private fun coroutineRequest2_6() {
    launch(Dispatchers.Main) {//在主线程启动协程
        val response = apiService.getWxarticle2()//在后台线程发起网络请求
        tvResult.text = sb.toString()//在主线程更新UI
    }
}

对比使用Retrofit+回调的方式,使用协程代码明显更加简洁清晰。

关于使用协程请求网络请参考 Kotlin协程请求网络

协程的挂起

看一个例子

private fun invokeMethod() {
    //注释1处,在主线程启动协程
    scope.launch(Dispatchers.Main) {
        Log.i(TAG, "getString: current thread " + Thread.currentThread().name)
        val result = getString()//注释2处,调用挂起函数
        etText.setText(result)//注释3处
    }
}

//挂起函数
private suspend fun getString(): String {
    //切换到IO线程
    return withContext(Dispatchers.IO) {
        Log.i(TAG, "getString: current thread " + Thread.currentThread().name)
        "empty string"
    }
}

输出结果

getString: current thread main
getString: current thread DefaultDispatcher-worker-2

注释1处,在主线程启动一个协程,就是指花括号里的这段代码,scope.launch(Dispatchers.Main) {...}

注释2处,当协程运行到挂起函数的时候,这个协程会被挂起。什么意思呢?

  1. 从挂起函数getString()的第一个挂起点开始当前线程(在这个例子中是主线程)不再运行协程中的代码了。第一个挂起点:可以暂时理解为withContext(Dispatchers.IO){...}花括号里面的代码块。

  2. 挂起函数执行完毕以后,协程从挂起点恢复,重新切回到当前线程(在这个例子中是主线程)继续执行协程中的代码。

etText.setText(result)

协程的挂起是非阻塞的是什么意思呢?

这个其实非常非常简单,没有什么高深的东西。看代码。

  1. 阻塞的例子。
//在主线程执行
btnSuspend.setOnClickListener {
    tvText1.text = getStringSuspend()
    tvText2.text = "兴百姓苦,亡百姓苦"
}

/**
 * 模拟耗时操作,2秒后返回字符串
 */
private fun getStringSuspend(): String {
    //让主线程睡两秒钟,其实就是阻塞了主线程
    Thread.sleep(2000)
    return "峰峦如聚,波涛如怒,山河表里潼关路,望西都意踌躇,伤心秦汉经行处,宫阙万间都做了土。"
}

在上面的例子中,tvText1获取显示字符串是一个耗时操作。注释1处,tvText2显示text肯定是在tvText1显示之后。也就是说当前线程:主线程 被阻塞了。当前线程被阻塞以后当前线程的后面的代码是无法执行的,必须等待阻塞结束。

  1. 协程的非阻塞
//在主线程执行
private var scope: CoroutineScope = CoroutineScope(Dispatchers.Main)
btnUnSuspend.setOnClickListener {
        scope.launch {
            tvText1.text = getStringUnSuspend()
        }
        //注释1处注意:这个代码一定要卸载协程的代码之外
        tvText2.text = "兴百姓苦,亡百姓苦"
}

/**
 * 模拟耗时操作,2秒后返回字符串。
 */
private suspend fun getStringUnSuspend(): String {
    delay(2000)
    return "峰峦如聚,波涛如怒,山河表里潼关路,望西都意踌躇,伤心秦汉经行处,宫阙万间都做了土。"
}

现在,tvText2先显示text,然后2秒后tvText1才显示了文字。这里主线程没有没阻塞,协程的delay(2000),实际上是在后台线程阻塞(延迟了)2秒,阻塞的是后台线程。

注释1处注意:这个代码一定要协程的代码之外。如果也写在launch的大括号之内了,那么tvText2也是在tvText1显示文字之后再显示。这也说明了在协程内部,代码也是顺序执行的,一个父协程会等待子协程执行完毕之后再继续往下执行。

scope.launch {
    tvText1.text = getStringUnSuspend()
    tvText2.text = "兴百姓苦,亡百姓苦"
}

/**
 * 模拟耗时操作,2秒后返回字符串。正确的的非阻塞,不阻塞当前线程,阻塞后台线程。
 */
private suspend fun getStringUnSuspend(): String {
    delay(2000)
    return "峰峦如聚,波涛如怒,山河表里潼关路,望西都意踌躇,伤心秦汉经行处,宫阙万间都做了土。"
}

结论:非阻塞式挂起,就是说挂起函数切到指定的线程执行去了,执行完毕以后会再切回到当前线程继续执行协程中的代码。在挂起函数切到别的线程执行的这段期间,当前线程是可以继续运行其他代码的。

关于协程的挂起记住一句话就行:挂起函数挂起协程时,不会阻塞协程所在的线程

参考链接:

相关文章

  • Kotlin协程一些概念理解

    协程的概念 协程就是 Kotlin 提供的一套线程封装的 API,使用协程可以让多线程之间的通信更加简单。总之一句...

  • Kotlin Coroutine 探索之旅

    协程 大家如果已经使用Kotlin语言进行开发,对协程这个概念应该不会很陌生。虽然在网上有很多Kotlin协程相关...

  • Kotlin 协程探索

    Kotlin 协程是什么? 本文只是自己经过研究后,对 Kotlin 协程的理解概括,如有偏差,还请斧正。 简要概...

  • Kotlin 协程学习笔记

    一、Kotlin 协程概念 Kotlin 协程提供了一种全新处理并发的方式,你可以在 Android 平台上使用它...

  • Kotlin 并发编程之"协程"

    Kotlin 并发编程之"协程" Kotlin协程简介 Kotlin, as a language, provid...

  • Kotlin协程探索(一) (Coroutine)

    Kotlin协程探索 (一)(Coroutine) PS:以下协程都特指Kotlin协程;且期望大家大概知道协程的...

  • 深入学习Kotlin协程(一)-协程是什么?

    Kotlin协程是什么? 协程并不是Kotlin提出的,其他的一些编程语言在早期就已经实现了协程,比如: Go、P...

  • java程序员的kotlin课(N):coroutines基础

    序言 如果对协程没有概念,不了解使用协程的好处,请参考《异步编程》系列文章 引入协程库 kotlin协程是以一个l...

  • Kotlin 协程学习教程之通俗易懂篇

    引言 协程并非Kotlin独有的,协程的概念在很早很早之前就有了,目前也有很多语言支持协程,本文以什么是协程、An...

  • 协程(1)

    协程是什么 协程并不是 Kotlin 提出来的新概念,其他的一些编程语言,例如:Go、Python 等都可以在语言...

网友评论

      本文标题:Kotlin协程一些概念理解

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