探索Kotlin协同程序的“select”表达

Kotlin Coroutines是一个非常强大的库,它附带了许多提供开箱即用功能的API。在本文中,我们将研究其中一个API,即选择表达式。

什么是选择表达式?🤨

在应用程序开发过程中,您可能有多个挂起的函数,并且您希望有一个业务逻辑,在挂起函数完成时对其结果进行操作。协同程序库通过select函数提供此功能。select函数充当类型安全构建器,其中提供了可在可挂起函数上注册回调的扩展函数。

在Kotlin协同程序中,“select”表达式可以同时等待多个挂起函数,并选择第一个可用的结果。它是一个挂起函数,在其中一个子句被选中或失败之前一直挂起。

选择表达式可以在应用程序开发过程中的一些用例中使用。例如

  • 有一种情况,当数据“a”或“B”中的任何人首先可用时,您希望处理“X”事件。
  • 您正在同时运行一些操作,无论哪个先完成(或返回结果),都要继续执行优胜者操作的结果,即数据竞赛。

…还有很多这样的用例。

让我们通过看例子来进一步探讨它。

使用它✨

正如我们讨论的一些用例,使用select的非常简单的例子可以是这样的👇🏻.

fun main() = runBlocking<Unit> {
    val winner = select<String> {
        data1().onAwait { it }
        data2().onAwait { it }
    }

    println("The winner = $winner") // prints "The winner = Hello"
}

fun data1() = GlobalScope.async {
    delay(1000)
    "Hello"
}

fun data2() = GlobalScope.async {
    delay(2000)
    "World"
}

在此示例中:

  • data1()和data2()是返回Deferred<String>的函数,其中data1需要1000ms来加载数据,data2需要2000ms。
  • 在“select”生成器中,onAwait()子句用于等待结果。
  • 当data1()返回结果时,它的值(“Hello”)被选中,因为它首先完成。因此,它是一个赢家。

让我们来看另一个例子,在这个例子中,您希望在用户在UI上执行多个选项之间的一些交互之后执行某个操作。select表达式可以这样使用👇🏻

suspend fun awaitCloseDialog() {
    select<Unit> {
        async { dialog.closeButton.awaitClick() }.onAwait { }
        async { dialog.okButton.awaitClick() }.onAwait { }
    }
    dialog.dismiss()
}

在本例中,当单击“关闭”按钮或单击“确定”按钮时,对话框将被关闭。

您还可以从Channel API生成的值中选择结果,如下所示👇🏻.

fun main() = runBlocking<Unit> {
    repeat(5) {
        val number = select<Int> {
            evenChannel.onReceive { it }
            oddChannel.onReceive { it }
        }
        println(number) // prints "0 1 3 2 5"
    }
}

val evenChannel = GlobalScope.produce<Int> {
    repeat(10) {
        delay(1000)
        if (it % 2 == 0) {
            send(it)
        }
    }
}

val oddChannel = GlobalScope.produce<Int> {
    repeat(10) {
        delay(500)
        if (it % 2 != 0) {
            send(it)
        }
    }
}

在本例中,evenChannel在1000ms后生成偶数,oddChannel在500ms后生成数字。因此,您可以看到奇数比偶数更容易被选中。

这些是选择表达式的一些基本示例。

注:当可以同时选择多个子句时,将优先选择执行它们的第一个子句,即选择函数偏向于第一个子句。使用selectUnbiased在子句中进行无偏选择,只需对选择进行洗牌/随机化。

支持的选择方法列表

这些API来自协同程序,受select表达式子句支持。

Receiver Suspending function Select clause
Job join onJoin
Deferred await onAwait
SendChannel send onSend
ReceiveChannel receive onReceive
ReceiveChannel receiveCatching onReceiveCatching
- delay onTimeout

您可以访问 官方文档,了解关于select表达式的更多可用API。

最后的想法🧐

在Kotlin中开发应用程序时,select表达式可以在许多用例中使用。但请记住,目前这个API是实验性的,这意味着相应声明的设计存在一些开放性问题,这些问题可能会(也可能不会)导致未来的更改。
我希望你喜欢这篇文章。如果你觉得这有帮助,请分享这篇文章。

分享就是关怀!🫶🏻

Thank you! 😃

为了帮助入门学习者或想深入的学习 Kotlin ,在这里分享一份《高级Kotlin强化实战学习手册(附Demo)》供Android开发者进阶学习 Kotlin,内容涵盖 Kotlin 入门教程、Kotlin实战避坑指南、Kotlin Jetpack 实战三大模块。希望能帮助到大家学习提升,如有需要参考的可以看下面 ↓↓↓

有需要的可以复制下方链接,传送直达!!!
https://docs.qq.com/doc/DQkdwVlhGS3pURnN1

第一章 Kotlin入门教程

  • Kotlin 概述

  • Kotlin 与 Java 比较

  • 巧用 Android Studio

  • 认识 Kotlin 基本类型

  • 走进 Kotlin 的数组

  • 走进 Kotlin 的集合

  • 集合问题

  • 完整代码

  • 基础语法

第二章 Kotlin 实战避坑指南

  • 方法入参是常量,不可修改

  • 不要 Companion 、INSTANCE ?

  • Java 重载,在 Kotlin 中怎么巧妙过渡一下?

  • Kotlin 中的判空姿势

  • Kotlin 复写 Java 父类中的方法

  • Kotlin “狠”起来,连TODO 都不放过!

  • is、as` 中的坑

  • Kotlin 中的 Property 的理解

  • also 关键字

  • takeIf 关键字

  • takeIf 关键字

  • 单例模式的写法

第三章 项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容