Coroutine 协程

协程是一种并发设计模式,可以使用它来简化异步执行的代码
协程有助于管理长时间运行的任务,如果管理不当,这些任务可能会阻塞主线程并导致应用无响应。

功能:
特点包括:

  1. 轻量 :您可以在单个线程上运行多个协程,因为协程支持挂起 suspend ,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
  2. 内存泄漏更少 :使用结构化并发机制在一个作用域内执行多项操作。
  3. 内置取消支持 :取消操作会自动在运行中的协程层次结构内传播。
  4. Jetpack 集成 :许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发。

  1. 协程域 CoroutineScope()
  • 挂起的函数代码块必须在 CoroutineScope 里执行
  • suspend 修饰的函数/方法
  • 挂起函数 这个函数耗时比较长
  • 不希望阻塞主线程挂起函数的执行必须在 CoroutineScope 内执行
  1. 协程上下文 CoroutineContext()
    这个协程在哪个线程上执行
  • Dispatchers.IO 子线程
  • Dispatchers.Main UI主线程
  • Dispatchers.Default 默认(当前线程)
  1. 任务开启
    使用 launch 开启一个同步任务 return: Job
  • a -> b-> c
  • 返回 Job 任务本身
  • 不需要返回值
    使用 async 开启一个异步任务return Deferred<>
  • a b c 同时做
  • 执行完一段代码之后它需要给我一个结果
  • 需要给我返回值
  • await() 获取对应的值,必须在一个协程内调用
  1. 使用 withContext() 切换线程
    Dispatchers.IO 子线程
    Dispatchers.Main Ul主线程
    最后一行是返回值

在特定的 CoroutineScop e中创建一个新的 CoroutineContext
它允许您在特定的作用域内设置 CoroutineContext,以便在该作用域内执行协程时使用该上下文。
这可以帮助您在协程中使用不同的上下文,例如切换线程或设置协程的调度器。

通常,withContext函数用于在协程中执行需要特定上下文的操作,例如在 IO线程执行网络请求 或 在主线程更新UI。

总之,withContext函数可以帮助您在协程中更改上下文,以便更好地控制协程的执行环境和调度方式。

  1. Flow 数据流
  • 当调用一个方法,在不同的时间/情况可能需要返回多个值
  • emit() 发射新的数据
  • collect() 订阅接受数据 必须在一个协程域内调用
  • flow{ } 创建一个Flow对象
  1. 协程域
    Activity / Fragment
  • lifecycleScope :
    为我们默认提供了一个CoroutineScope 直接使用就可以了
    如果是自己创建,自己需要管理这个协程的生命周期(创建->销毁)

ViewModel

  • ViewModelScope

除此以外就需要自已创建 CoroutineScope


步骤

导入依赖:
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")

用 suspend 标识耗时的操作,这个耗时操作只能在协程域里面执行

1
2
3
suspend fun count(){

}

(1)创建一个协程域

1
val scope = CoroutineScope(Dispatchers.lO)

(2)在这个协程域上开启一个任务

  • 使用 launch 开启一个同步任务 a-> b-> c 任务默认就在 scope 所在的区域执行,会返回 Job

    1
    2
    3
    4
    5
    6
    7
    8
    scope.launch{ //默认不指定就在 scope 规定的线程
    count()
    }

    //↓可以切换线程
    scope.launch(Dispatchers.lO){ //另外指定线程
    count()
    }
  • async 开启一个异步任务

    1
    2
    3
    4
    5
    6
    7
    val sum2 = scope.async{
    var sum = sum1.await()
    for (i in 1 < .. < 100){
    sum += i
    }
    sum
    }

withContext(Dispatchers.Main) 切换上下文 切换代码执行的scope 切换线程

1
2
3
4
5
6
7
8
9
10

suspend fun count(){
for (i in 1..100){
withContext(Dispatchers.Main){
mTextView.text = "$i"
}
delay( timeMillis: 200)
}
}

Flow

在Kotlin中,Flow 的 emit 方法用于发射(emit)一个新的元素到 Flow 中,而 collect 方法用于从Flow中收集(collect)元素并进行处理。

  1. emit方法:emit方法是Flow的一个扩展函数,用于向Flow中发射一个新的元素。当调用emit方法时,会将指定的元素发送到Flow中,并通知Flow的观察者(collect方法)有新的元素可用。emit方法通常用于在Flow中生成新的元素,例如在网络请求或数据库查询返回结果后,将结果发射到Flow中。

示例代码:

1
2
3
4
5
6
7
fun generateNumbers(): Flow<Int> = flow {
for (i in 1..5) {
emit(i)
}
}

val numbersFlow = generateNumbers()
  1. collect 方法:collect 方法是Flow的一个挂起函数,用于从 Flow 中收集元素并进行处理。当调用 collect 方法时,会阻塞当前协程直到 Flow 中有新的元素可用,然后处理这个元素。 collect 方法通常用于订阅 Flow 并处理其中的元素,例如打印元素、更新 UI 等操作。

示例代码:

1
2
3
4
5
6
val numbersFlow = generateNumbers()
viewModelScope.launch {
numbersFlow.collect { number ->
Log.d("FlowExample", "Received number: $number")
}
}

通过 emit 方法向 Flow 中发射新的元素,然后通过 collect 方法从 Flow 中收集并处理这些元素,可以实现在 Flow 中生成和处理数据的功能。


cancel() 取消该任务
join() 等待任务做完
cancelAneJoin() 将 CoroutineScope 的属性 isActive 转换为 false

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信