使用 IntelliJ IDEA 调试 Kotlin Flow – 教程
本教程演示了如何创建 Kotlin Flow 并使用 IntelliJ IDEA 进行调试。
本教程假定你已对 协程 和 Kotlin Flow 概念有所了解。
创建 Kotlin Flow
创建一个具有慢速发射器和慢速收集器的 Kotlin Flow:
在 IntelliJ IDEA 中打开一个 Kotlin 项目。如果你没有项目,可以创建一个。
要在 Gradle 项目中使用
kotlinx.coroutines
库,请将以下依赖项添加到build.gradle(.kts)
:kotlindependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") }
groovydependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2' }
对于其他构建系统,请参阅
kotlinx.coroutines
README 中的说明。打开
src/main/kotlin
目录中的Main.kt
文件。src
目录包含 Kotlin 源文件和资源。Main.kt
文件包含将打印Hello World!
的示例代码。创建返回一个包含三个数字的 Flow 的
simple()
函数:kotlinimport kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlin.system.* fun simple(): Flow<Int> = flow { for (i in 1..3) { delay(100) emit(i) } }
更改
main()
函数中的代码:- 使用
runBlocking()
代码块来包裹一个协程。 - 使用
collect()
函数收集发射的值。 - 使用
delay()
函数来模拟 CPU 密集型代码。它将协程挂起 300 毫秒,而不阻塞线程。 - 使用
println()
函数打印从 Flow 收集到的值。
kotlinfun main() = runBlocking { simple() .collect { value -> delay(300) println(value) } }
- 使用
点击 Build Project 构建代码。
调试协程
在调用
emit()
函数的行设置断点:点击屏幕顶部运行配置旁边的 Debug,以调试模式运行代码。
Debug 工具窗口出现:
- Frames 标签页包含调用栈。
- Variables 标签页包含当前上下文中的变量。它告诉我们 Flow 正在发射第一个值。
- Coroutines 标签页包含有关正在运行或已挂起的协程的信息。
通过点击 Debug 工具窗口中的 Resume Program 恢复调试会话。程序在同一断点处停止。
现在 Flow 发射第二个值。
被优化掉的变量
如果你使用 suspend
函数,在调试器中,你可能会在变量名称旁边看到“was optimized out”文本:
此文本表示变量的生命周期已缩短,且该变量不再存在。 调试带有被优化掉的变量的代码很困难,因为你无法看到它们的值。 你可以使用 -Xdebug
编译器选项禁用此行为。
切勿在生产环境中使用此标志:
-Xdebug
可能导致内存泄漏。
添加并发运行的协程
打开
src/main/kotlin
目录中的Main.kt
文件。增强代码以并发运行发射器和收集器:
- 添加对
buffer()
函数的调用,以并发运行发射器和收集器。buffer()
会存储发射的值,并在一个单独的协程中运行 Flow 收集器。
kotlinfun main() = runBlocking<Unit> { simple() .buffer() .collect { value -> delay(300) println(value) } }
- 添加对
点击 Build Project 构建代码。
调试带有两个协程的 Kotlin Flow
在
println(value)
处设置一个新断点。点击屏幕顶部运行配置旁边的 Debug,以调试模式运行代码。
Debug 工具窗口出现。
在 Coroutines 标签页中,你可以看到有两个协程正在并发运行。由于
buffer()
函数,Flow 收集器和发射器在单独的协程中运行。buffer()
函数会缓冲从 Flow 发射的值。 发射器协程处于 RUNNING(运行中)状态,而收集器协程处于 SUSPENDED(已挂起)状态。通过点击 Debug 工具窗口中的 Resume Program 恢复调试会话。
现在收集器协程处于 RUNNING(运行中)状态,而发射器协程处于 SUSPENDED(已挂起)状态。
你可以深入探查每个协程来调试你的代码。