Debug Kotlin Flow using IntelliJ IDEA
最近更新 | 2020-09-15 |
The tutorial assumes you have prior knowledge of the coroutines and Kotlin Flow concepts.
Debugging works for
kotlinx-coroutines-core
version 1.3.8 or later.
Create a Kotlin flow
Create a Kotlin flow with a slow emitter and a slow collector:
-
Open a Kotlin project in IntelliJ IDEA. If you don't have a project, create one.
-
Open the
main.kt
file insrc/main/kotlin
.The
src
directory contains Kotlin source files and resources. Themain.kt
file contains sample code that will printHello World!
. -
Create the
simple()
function that returns a flow of three numbers:- Use the
delay()
function to imitate CPU-consuming blocking code. It suspends the coroutine for 100 ms without blocking the thread. - Produce the values in the
for
loop using theemit()
function.
import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import kotlin.system.* fun simple(): Flow<Int> = flow { for (i in 1..3) { delay(100) emit(i) } }
- Use the
-
Change the code in the
main()
function:- Use the
runBlocking()
block to wrap a coroutine. - Collect the emitted values using the
collect()
function. - Use the
delay()
function to imitate CPU-consuming code. It suspends the coroutine for 300 ms without blocking the thread. - Print the collected value from the flow using the
println()
function.
fun main() = runBlocking { simple() .collect { value -> delay(300) println(value) } }
- Use the
-
Build the code by clicking Build Project.
Debug the coroutine
-
Set a breakpoint at the at the line where the
emit()
function is called: -
Run the code in debug mode by clicking Debug next to the run configuration at the top of the screen.
The Debug tool window appears:
- The Frames tab contains the call stack.
- The Variables tab contains variables in the current context. It tells us that the flow is emitting the first value.
- The Coroutines tab contains information on running or suspended coroutines.
-
Resume the debugger session by clicking Resume program in the Debug tool window. The program stops at the same breakpoint.
Now the flow emits the second value.
Add a concurrently running coroutine
-
Open the
main.kt
file insrc/main/kotlin
. -
Enhance the code to run the emitter and collector concurrently:
- Add a call to the
buffer()
function to run the emitter and collector concurrently.buffer()
stores emitted values and runs the flow collector in a separate coroutine.
fun main() = runBlocking<Unit> { simple() .buffer() .collect { value -> delay(300) println(value) } }
- Add a call to the
-
Build the code by clicking Build Project.
Debug a Kotlin flow with two coroutines
-
Set a new breakpoint at
println(value)
. -
Run the code in debug mode by clicking Debug next to the run configuration at the top of the screen.
The Debug tool window appears.
In the Coroutines tab, you can see that there are two coroutines running concurrently. The flow collector and emitter run in separate coroutines because of the
buffer()
function. Thebuffer()
function buffers emitted values from the flow. The emitter coroutine has the RUNNING status, and the collector coroutine has the SUSPENDED status. -
Resume the debugger session by clicking Resume program in the Debug tool window.
Now the collector coroutine has the RUNNING status, while the emitter coroutine has the SUSPENDED status. You can dig deeper into each coroutine to debug your code.