Kotlin协程的介绍

一,什么是协程:

官方的介绍:

协程是一种并发设计模式,在Android平台上可以使用协程简化异步执行代码。(协程可以使我们是同步的代码形式实现异步任务的执行)

协程的特点:

  1. 轻量:一个线程上可以运行多个协程,协程支持挂起,协程的挂起不会阻塞运行协程的线程。挂起比阻塞更节省内存,也能让线程得到充分的利用。
  2. 内存泄漏更少:使用结构化并发在一个范围内(协程作用域)运行多项操作。
  3. 内置取消支持:取消通过正在运行的协程层次结构,自动传播。
  4. Jetpack集成:JetPack库提供了全面支持协程的扩展,提供了类似LifecycleScope,ViewModelScope绑定生命周期的作用域。

二,协程的使用:

1,添加相关依赖:

project的build.gradle中添加Kotlin编译插件

js 复制代码
dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32"
}

app的build.gradle中添加协程相关的依赖库。

js 复制代码
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"
}

2,构建启动一个协程

构建启动协程常用三种方式:

runBlocking:创建并启动一个新的线程,并且会阻塞当前的线程,直到协程内所有逻辑 和 子协程都执行完毕。项目中用不了,主要在@test测试代码中使用。

launch: 启动创建一个新的协程而不阻塞当前的线程。返回一个协程引用Job对象。

js 复制代码
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job 

context: 协程的上下文,协程的运行环境。可以是多个上下文组合,包括调度器(Dispatchers.Default)、协程本身的job、协程的名称(CoroutineName)、异常处理器(CoroutineExceptionHandler)

start: 协程的启动模式,立即启动 或 懒启动(Lazy)

block:是一个无参、无返回值的挂起函数,我们业务逻辑实现方法。

Job:协程的任务对象,可以通过Job 获取协程的状态和对协程执行操作。isActive()判断是否活跃,start()启动协程,cancel取消协程,join()挂起协程直到此job执行完成等,

java 复制代码
fun test(){
    val job = MainScope().launch{
        Log.i("wang", "launch")
        delay(1000)//挂起函数
        Log.i("wang", "after one second")
        //两个launch构建并启动
        val job1= launch {
            delay(3000)
            Log.i("wang", "launch1")
        }
        launch {
            delay(3000)
            Log.i("wang", "launch2")
        }
        job1.join()//等待协程执行完,也是挂起函数,非阻塞的
        launch {
            delay(2000)
            Log.i("wang", "launch3")
        }
    }
    Log.i("wang", "end")
}

运行结果:

js 复制代码
2025-04-28 09:53:32.449 14296-14296 wang                    I  end
2025-04-28 09:53:32.452 14296-14296 wang                    I  launch
2025-04-28 09:53:33.454 14296-14296 wang                    I  after one second
2025-04-28 09:53:36.467 14296-14296 wang                    I  launch1
2025-04-28 09:53:36.471 14296-14296 wang                    I  launch2
2025-04-28 09:53:38.480 14296-14296 wang                    I  launch3

async:启动创建一个新的协程而不阻塞当前的线程。返回一个协程引用Deffered对象。

js 复制代码
public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T> 

block: 无参、有返回值T的挂起函数,较launch多了返回值。

Deffered: 是Job的子类,较Job多了个await()挂起函数,用于等待协程执行的结果返回值。

java 复制代码
fun testAsync(){
    MainScope().launch {
        val deferred1 = async {
            delay(1000)
            Log.i("wang", "deferred1 execute")
            100
        }
        val deferred2 = async {
            delay(2000)
            Log.i("wang", "deferred2 execute")
            200
        }
        val deferred3 = async {
            delay(3000)
            Log.i("wang", "deferred3 execute")
            300
        }
        Log.i("wang", "sum = " + (deferred1.await() + deferred2.await() + deferred3.await()))
    }
}

运行结果:

js 复制代码
2025-04-27 18:28:37.134  9747-9747  wang                    com.example.myapplication            I  deferred1 execute
2025-04-27 18:28:38.134  9747-9747  wang                    com.example.myapplication            I  deferred2 execute
2025-04-27 18:28:39.136  9747-9747  wang                    com.example.myapplication            I  deferred3 execute
2025-04-27 18:28:39.137  9747-9747  wang                    com.example.myapplication            I  sum = 600

3,协程的作用域

GlobalScope:作用域是全局,与应用程序的生命周期绑定。

coroutineScope: 创建一个独立协程作用域,所有的子协程都执行完了以后才结束自身,当前有一个子协程抛出异常后,所有未执行完成的子协程+自身都会停止执行。

superVisorScope: 同上类似,不同是子协程出现异常,不会影响父协程,也不会影响同阶的子协程。相当于在launch(SuperVisorJob())

MainScope():上下文是SupervisorJob() + Dispatchers.Main。一个在主线程执行的协程作用域。

lifecycleScope:具有生命周期感知的协程作用域,与Lifecycle生命周期绑定,生命周期结束时,此作用域将被取消。

viewModelScope: 与lifecycleScope类似,与ViewModel的生命周期绑定。

4,协程调度器

Kotlin 提供了四个调度器,您可以使用它们来指定应在何处运行协程:

调度器 介绍
Dispatchers.Default 默认调度器,非主线程。CPU密集型任务调度器。用于json解析,数据处理
Dispatchers.Main UI调度器, Andorid 上的主线程。用于UI更新
Dispatchers.Unconfined 非指定线程的协程调度器,取决于启动的线程。
Dispatchers.IO IO调度器,非主线程,执行的线程是IO线程。用于网络请求,数据库处理、文件读写

5,suspend挂起函数

suspend:是kotlin的核心关键字,使用suspend关键字修饰的函数叫挂起函数,挂起函数只能在协程中或其他挂起函数中执行。

协程在执行到有suspend标记的挂起函数时,当前函数会被挂起(暂停),直到该挂起函数内部逻辑完成,才会在挂起的地方resume恢复继续执行,而不会阻塞运行协程的线程。

java 复制代码
private fun testSuspend(){
    //启动了一个协程,去执行一个挂起函数
    Log.i("wang", "start")
    MainScope().launch {
        Log.i("wang", "start")
        val result = doWorkBackGroup()
        Log.i("wang", "result$result")
    }
}

private suspend fun doWorkBackGroup(): String{
    //模拟耗时任务
    delay(1000)
    Log.i("wang", "doWorkBackGroup end")
    return "hello world"
}

执行结果如下:

js 复制代码
2025-04-28 17:34:21.049 27706-27706 wang                  I  start
2025-04-28 17:34:22.051 27706-27706 wang                  I  doWorkBackGroup end
2025-04-28 17:34:22.052 27706-27706 wang                  I  resulthello world

源码分析:KotlinBytecode后在deCompile后的代码如下,多了一个编译器加的参数Continuation,有个接口方法resumeWith(result), 即挂起函数执行完毕后恢复的回调。

java 复制代码
private final Object doWorkBackGroup(Continuation $completion) {
kotlin 复制代码
@kotlin.SinceKotlin public interface Continuation<in T> {
    public abstract val context: kotlin.coroutines.CoroutineContext

    public abstract fun resumeWith(result: kotlin.Result<T>): kotlin.Unit
}
相关推荐
FunnySaltyFish12 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker18 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker2 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
A0微声z4 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton4 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream4 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin
RdoZam4 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
Kapaseker5 天前
研究表明,开发者对Kotlin集合的了解不到 20%
android·kotlin
糖猫猫cc5 天前
Kite:两种方式实现动态表名
java·kotlin·orm·kite
如此风景6 天前
kotlin协程学习小计
android·kotlin