Kotlin流程介绍
简介
用async builder启动的悬浮函数和/或coroutines会返回单个值。这些值可以是字符串、整数、布尔值,甚至是列表。但是,如果我们想返回多个异步计算的值呢?以从数据库加载一个大的列表为例。
使用默认的coroutine构建器将一次性返回整个列表。然而,这将花费更长的时间,并使我们的程序变得缓慢。在这种情况下,最好的方法是在计算后返回单个值,而不是整个列表。这就是流量的作用。
前提条件
要继续学习本教程,你需要。
- 安装有IntelliJ IDEA。
- 对[Kotlin]编程语言有基本了解。
- 对循环程序有基本的了解。
什么是流
流程是由多个异步计算的值组成的流。流程在完成计算后会立即释放出数值。一个流由一个生产者和一个消费者组成。顾名思义,生产者发射数值,而消费者接收数值。
让我们看看如何在Kotlin程序中创建和使用流。
第1步 - 创建一个Kotlin项目
在这一步,我们要创建一个由Gradle管理的Kotlin控制台项目。
打开IntelliJ,选择New Project 。在下一个窗口中,选择Kotlin,控制台应用程序。选择项目的JDK,如果没有安装,就下载一个。

给项目起个名字,然后点击下一步。将下一个屏幕保留为默认设置,然后点击完成。
等待项目构建完成。
流程是建立在coroutines之上的。
打开build.gradle 文件,添加以下依赖关系。
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
第2步 - 创建一个生产者
为了创建一个流程,我们需要一个生产者。正如我们前面提到的,生产者在计算出数值后会立即发射出来。那么,我们如何创建一个生产者呢?打开你的main.kt 文件,用下面的代码替换主函数。
suspend fun main() {
val flow = flow {
for (i in 1..10){
delay(1000)
emit(i)
}
}
}
我们将主函数标记为暂停,因为它以后会调用其他暂停的函数。我们使用流程生成器来创建一个流程生成器。构建器接收一个可选的显式类型参数。如果没有明确的类型,类型参数将被设置为发射值。在我们的例子中,流量发射的是一个整数,因此,流量类型是整数。
我们的流程发射的是1到10的整数值。我们已经使用delay 来模拟一个长期运行的任务。然而,这还不够。现在运行主函数不会给你任何输出。首先,我们必须创建一个消费者来接收这些值。
第3步 - 创建一个消费者
一个流是一个冷的流。哦,对了,我们提到流是一个流,但我们没有说它是冷的。
什么是冷流?🤔
我们有两种类型的流,一种是冷流,一种是热流。冷流在人们开始收集价值之前不会开始产生价值。另一方面,热流则立即开始产生价值。
流量就是一个冷流的例子。因此,为了获得这些值,我们需要收集它们。流构建器给了我们一个特殊的函数collect 来收集它所发出的值。
在主函数中添加以下代码。
val job = GlobalScope.launch {
flow.collect {
println(it)
}
}
job.join()
collect 函数需要在一个coroutine内调用。因此,我们为它启动一个coroutine。collect 函数接收了一个lambda函数,每次收到一个值时都会调用。在我们的例子中,我们只是将值打印到控制台。
运行主函数。你应该看到一秒钟后显示一个值。
这就是了,你已经创建了你的第一个流程。
第4步 - 测试背压
流量的一个重要特点是支持背压。当消费者消耗数据的速度慢于生产者生产数据的速度时,就会出现背压。当生产者没有意识到背压时,这可能导致数据丢失。幸运的是,流量是知道背压的。
让我们来证明这一点。
在collect lambda函数中添加两秒的延迟。
delay(2000)
该函数应该看起来像这样。
val job = GlobalScope.launch {
flow.collect {
delay(2000)
println(it)
}
}
运行主函数。注意到所有的值都显示出来了,但延迟时间是三秒,而不是两秒。这是因为生产者和消费者默认运行在同一个程序上。因此,延迟的时间相加。为了解决这个问题,我们使用buffer 函数,也就是说,我们在一个单独的coroutine上运行消费者。
用下面的代码替换collect函数。
val job = GlobalScope.launch {
flow.buffer().collect {
delay(2000)
println(it)
}
}
再次运行主函数。这一次的延迟是两秒,这是我们所期望的。
然而,最重要的是,我们没有丢失任何数值,这意味着流量真正支持背压。
总结
在这篇文章中,我们已经了解了Kotlin中流量的基本知识。我们看到了流是如何被创建和消耗的。我们还证明了流是知道背压的。这就是你开始使用flow的全部需要。