Kotlin学习笔记(六)--kotlin协程的挂起

launchasync都可以创建协成,都返回Coroutine,只不过async返回的Coroutine多实现了Deferred接口(延迟获取结果)。

调用Deferred.await()就可以获取到结果,之前的例子中

val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main)
coroutineScope.launch {
    val avatar: Deferred<Any> = async { api.getAvatar(user) } // 获取用户头像 返回Deferred类型
	val logo: Deferred<Any> = async { api.getCompanyLogo(user) } // 获取用户所在公司的 logo 返回Deferred类型
    show(avatar.await(), logo.await())  //调用deferred的await获取协成返回的数据
}

await函数

public suspend fun await(): T // suspend 表示该函数挂起

suspend挂起

创建的协成在执行到suspend函数的时候,就会从当前线程被挂起,暂时不继续执行该协成代码。例

val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main)
coroutineScope.launch {
    val image = suspendingGetImage("imageID")  // 获取图片
    iv.setImageBitmap(image)           // 显示出来
}

suspend fun suspendingGetImage(id: String) {
    withContext(Dispatchers.IO) {
        //网络获取图片
    }
}

执行到suspendingGetImage()的时候被挂起,从suspend函数开始继续往下在suspend函数指定的线程执行,比如例子中的withContext指定的Dispatchers.IO线程。

Dispatchers有三种类型

Dispatchers.Main:Android 中的主线程
Dispatchers.IO:针对磁盘和网络 IO 进行了优化,适合 IO 密集型的任务,比如:读写文件,操作数据库以及网络请求
Dispatchers.Default:适合 CPU 密集型的任务,比如计算

在指定的线程执行完后会自动切回到原有的线程,即例子中的主线程

要求 suspend 函数只能在协程里或者另一个 suspend 函数里被调用,还是为了要让协程能够在 suspend 函数切换线程之后再切回来。

怎么实现挂起操作的

自定义suspend声明的函数只是表示该函数要挂起,但是挂起操作还是kotlin框架里的挂起函数例如withContext,来实现挂起操作,如果只有suspend声明,IDE也会提示该关键字是多余的,因为没有通过挂起函数来指定要切换的线程。

因为你这个函数实质上并没有发生挂起,那你这个 suspend 关键字只有一个效果:就是限制这个函数只能在协程里被调用,
如果在非协程的代码中调用,就会编译不通过。

所以,创建一个 suspend 函数,为了让它包含真正挂起的逻辑,要在它内部直接或间接调用 Kotlin 自带的 suspend 函数,
你的这个 suspend 才是有意义的。

其他挂起函数

除了withContext挂起函数还有delay作用是是等待一段时间后再继续往下执行代码。例

suspend fun suspendingGetImage(id: String) {
    delay(5)
    //其他事
}

你可能感兴趣的:(Kotlin)