• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[//]: # (title: Debug Kotlin Flow using IntelliJ IDEA – tutorial)
2
3This tutorial demonstrates how to create Kotlin Flow and debug it using IntelliJ IDEA.
4
5The tutorial assumes you have prior knowledge of the [coroutines](coroutines-guide.md) and [Kotlin Flow](flow.md#flows) concepts.
6
7> Debugging works for `kotlinx-coroutines-core` version 1.3.8 or later.
8>
9{type="note"}
10
11## Create a Kotlin flow
12
13Create a Kotlin [flow](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/flow.html) with a slow emitter and a slow collector:
14
151. Open a Kotlin project in IntelliJ IDEA. If you don't have a project, [create one](jvm-get-started.md#create-an-application).
16
172. Open the `main.kt` file in `src/main/kotlin`.
18
19    The `src` directory contains Kotlin source files and resources. The `main.kt` file contains sample code that will print `Hello World!`.
20
213. Create the `simple()` function that returns a flow of three numbers:
22
23    * Use the [`delay()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html) function to imitate CPU-consuming blocking code. It suspends the coroutine for 100 ms without blocking the thread.
24    * Produce the values in the `for` loop using the [`emit()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow-collector/emit.html) function.
25
26    ```kotlin
27    import kotlinx.coroutines.*
28    import kotlinx.coroutines.flow.*
29    import kotlin.system.*
30
31    fun simple(): Flow<Int> = flow {
32        for (i in 1..3) {
33            delay(100)
34            emit(i)
35        }
36    }
37    ```
38
394. Change the code in the `main()` function:
40
41    * Use the [`runBlocking()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) block to wrap a coroutine.
42    * Collect the emitted values using the [`collect()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect.html) function.
43    * Use the [`delay()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html) function to imitate CPU-consuming code. It suspends the coroutine for 300 ms without blocking the thread.
44    * Print the collected value from the flow using the [`println()`](https://kotlinlang.org/api/latest/jvm/stdlib/stdlib/kotlin.io/println.html) function.
45
46    ```kotlin
47    fun main() = runBlocking {
48        simple()
49            .collect { value ->
50                delay(300)
51                println(value)
52            }
53    }
54    ```
55
565. Build the code by clicking **Build Project**.
57
58    ![Build an application](flow-build-project.png)
59
60## Debug the coroutine
61
621. Set a breakpoint at the line where the `emit()` function is called:
63
64    ![Build a console application](flow-breakpoint.png)
65
662. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
67
68    ![Build a console application](flow-debug-project.png)
69
70    The **Debug** tool window appears:
71    * The **Frames** tab contains the call stack.
72    * The **Variables** tab contains variables in the current context. It tells us that the flow is emitting the first value.
73    * The **Coroutines** tab contains information on running or suspended coroutines.
74
75    ![Debug the coroutine](flow-debug-1.png)
76
773. Resume the debugger session by clicking **Resume Program** in the **Debug** tool window. The program stops at the same breakpoint.
78
79    ![Debug the coroutine](flow-resume-debug.png)
80
81    Now the flow emits the second value.
82
83    ![Debug the coroutine](flow-debug-2.png)
84
85## Add a concurrently running coroutine
86
871. Open the `main.kt` file in `src/main/kotlin`.
88
892. Enhance the code to run the emitter and collector concurrently:
90
91    * Add a call to the [`buffer()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/buffer.html) function to run the emitter and collector concurrently. `buffer()` stores emitted values and runs the flow collector in a separate coroutine.
92
93    ```kotlin
94    fun main() = runBlocking<Unit> {
95        simple()
96            .buffer()
97            .collect { value ->
98                delay(300)
99                println(value)
100            }
101    }
102    ```
103
1043. Build the code by clicking **Build Project**.
105
106## Debug a Kotlin flow with two coroutines
107
1081. Set a new breakpoint at `println(value)`.
109
1102. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
111
112    ![Build a console application](flow-debug-3.png)
113
114    The **Debug** tool window appears.
115
116    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.
117    The `buffer()` function buffers emitted values from the flow.
118    The emitter coroutine has the **RUNNING** status, and the collector coroutine has the **SUSPENDED** status.
119
1203. Resume the debugger session by clicking **Resume Program** in the **Debug** tool window.
121
122    ![Debugging coroutines](flow-debug-4.png)
123
124    Now the collector coroutine has the **RUNNING** status, while the emitter coroutine has the **SUSPENDED** status.
125
126    You can dig deeper into each coroutine to debug your code.
127