Kotlin协程笔记

2020-05-15  本文已影响0人  没有故事的男童鞋

引入携程所需库

第一步:项目级build.gradle中

buildscript {
 ext.kotlin_coroutines = '1.3.1'
}

第二步:Module级别build.gradle中

dependencies {
 //                                       👇 依赖协程核心库
 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
 //                                       👇 依赖当前平台所对应的平台库,如Android或js
 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"
 //协程的声明周期库,该库可以选加,是让协程的生命周期和Activity的周期保持一致
 implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha02'
}

注:核心库和平台库版本需要保持一致

协程是什么

相关名词

1、GloabScope:全局范围
2、Coroutine:协程
3、suspend:挂起、暂停

相关方法介绍

runBlocking :一般用于 单元测试中,是线程阻塞的

launch(Dispatchers.IO){}:可以用来切线程

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

withContext(){}:切换线程,当需要频繁的进行线程切换时,因为可以自动切回原来的线程,所以相应的代码嵌套层次没那么多,并在闭包内的逻辑执行结束后自动切回原来的线程,继续执行

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

Async{}:返回的协程实现了Deferred。可以使用wait()方法

创建携程的方法

方法一:使用runBlocking 顶层函数,适用于单元测试的情况,是线程阻塞的,一般正常的业务开发不会使用

runBlocking{个人理解:此次相当于开启一个线程,但是会阻塞当前线程,相当于一个耗时任务???
  getImage(imageId)
}

方法二:使用GlobalScope 单例对象,直接调用launch开启协程,不会阻塞线程,但是实际开发中也一般不会使用,因为它的生命周期和APP的生命周期是一致的

GlobalScope.launch{
  getImage(imageId)
}

方法三:通过CoroutineContext创建一个CoroutineScope(接口)对象,需要一个类型为CoroutineContext的参数。开发中推荐这种方法,--coroutineContext?????

val coroutineScope = CoroutineScope(coroutineContext)
coroutineScope.launch{
  getImage(imageId)
}

方法四:主要用于在一个协程中开启另一个协程,直接在普通代码中无法使用

launch{
  
}

方法五:该方法与launch类似,也是在协程中使用

async{
  
}

async 和 launch对比

相同点:都可以用来启动一个协程,返回的都是Coroutine

不同点:

  • async返回的Coroutine还实现了Deferred(意思是延迟,也就是结果稍后才能拿到。)接口。可以使用await暂停函数来返回result

  • launch可启动新协程而不将结果返回给调用方

async使用场景:如现在需要展示公司LOGO和个人头像,但是需要等待两者都返回了,才可以去显示,两者同时进行,然后等较慢的执行完毕就可以显示了,所花费的时间就是两个中较长的一个,而不是两者之和

coroutineScope.launch(Dispatchers.Main) {
    //                      👇  async 函数启动新的协程
    val avatar: Deferred = async { api.getAvatar(user) }    // 获取用户头像
    val logo: Deferred = async { api.getCompanyLogo(user) } // 获取用户所在公司的 logo
    //            👇          👇 获取返回值
    show(avatar.await(), logo.await())                     // 更新 UI
}

挂起的本质

什么是挂起:挂起就是稍后会自动切回来的操作

在协程中,我们挂起的对象既不是线程,也不是函数,而是我们挂起的对象是协程,就是launch和async函数中的闭包的代码块,而launch和async或者其他函数创建的协程在执行到某一个suspend函数的时候,这个函数就会被挂起,或者说从当前线程中脱离。

自定义suspend函数

上一篇下一篇

猜你喜欢

热点阅读