【Kotlin】 自学(十)-Kotlin协程

339 阅读2分钟

Kotlin协程是什么

简单理解就是一个"线程框架",由Kotlin官方提供的线程API,类似JavaExecutorAndroidAsyncTask. 为什么使用它呢?方便,特别是它可以用看起来同步的方式写出异步代码,这也是人们常说的非阻塞式挂起.

这里举个例子,通过接口请求获取名字,然后显示在TextView

正常使用:

api.getUser()
	.enqueue(object: Callback{
    	
       override fun onFailure(){
       }
       
        override fun onResonse(Resonse response){
        	runOnUiThread{
            	nameTv.text=response.body()?.name
            }
       }
    
    }
    )

使用协程:

 	GlobalScope.launch() {
            //网络请求(IO 线程)
            val user = api.getUser()
            //更新 UI(主线程)
            nameTv.text = user.name
        }

省去了回调,同时看上去跟同步请求差不多,很清晰

还比如下面这种场景,同时请求A,B两个接口,两个接口都请求完毕后整合数据并显示,如果我们不使用协程,那么我们一般就是改成顺序请求,因为并发请求不太好弄,这样就会消耗一些时间,同时还会有回调嵌套的问题;如果使用协程呢,就可以完美实现

  	    GlobalScope.launch(Dispatchers.Main) {
            // 获取A接口
            val A = async { api.getA() }
            // 获取B接口
            val B = async { api.getB() }
            // 合并结果
            val merged = erge(A, B)
            // 更新 UI
            show(merged)
        }

Kotlin协程怎么用

引入库

项目根目录下的 build.gradle :

buildscript {
    ...
    ext.kotlin_coroutines = '1.3.1'
    ...
}

Module 下的 build.gradle :

    // 依赖协程核心库
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
    // 依赖当前平台所对应的平台库
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"

使用

创建协程

  		// 方法一,使用 runBlocking 顶层函数
        //通常适用于单元测试的场景,而业务开发中不会用到这种方法,因为它是线程阻塞的
        runBlocking {

        }

        // 方法二,使用 GlobalScope 单例对象
        GlobalScope.launch {
        }

        // 方法三,自行通过 CoroutineContext 创建一个 CoroutineScope 对象
        //  需要一个类型为 CoroutineContext 的参数
        val coroutineScope = CoroutineScope(context)
        coroutineScope.launch {
        }

这个 launch 函数表示我要创建一个新的协程,并在指定的线程上运行它。这个被创建、被运行的所谓「协程」是谁?就是你传给 launch 的那些代码,这一段连续代码叫做一个「协程」。

切线程

coroutineScope.launch(Dispatchers.Main) {
    ...
    withContext(Dispatchers.IO) {
        ...
    }
    ...
    withContext(Dispatchers.IO) {
        ...
    }
    ...
}

我们也可以把withContext放在一个函数里面.但是这个函数必须使用suspend

  	suspend fun getImage() {
            withContext(Dispatchers.IO) {

            }
        }

这个suspendKotlin 协程最核心的关键字,代码执行到 suspend 函数的时候会『挂起』,并且这个『挂起』是非阻塞式的,它不会阻塞你当前的线程。