• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<contribute-url>https://github.com/Kotlin/kotlinx.coroutines/edit/master/docs/topics/</contribute-url>
2
3
4[//]: # (title: Debug Kotlin Flow using IntelliJ IDEA – tutorial)
5
6This tutorial demonstrates how to create Kotlin Flow and debug it using IntelliJ IDEA.
7
8The tutorial assumes you have prior knowledge of the [coroutines](coroutines-guide.md) and [Kotlin Flow](flow.md#flows) concepts.
9
10## Create a Kotlin flow
11
12Create 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:
13
141. Open a Kotlin project in IntelliJ IDEA. If you don't have a project, [create one](jvm-get-started.md#create-a-project).
152. To use the `kotlinx.coroutines` library in a Gradle project, add the following dependency to `build.gradle(.kts)`:
16
17   <tabs group="build-script">
18   <tab title="Kotlin" group-key="kotlin">
19
20   ```kotlin
21   dependencies {
22       implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%")
23   }
24   ```
25
26   </tab>
27   <tab title="Groovy" group-key="groovy">
28
29   ```groovy
30   dependencies {
31       implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%'
32   }
33   ```
34
35   </tab>
36   </tabs>
37
38   For other build systems, see instructions in the [`kotlinx.coroutines` README](https://github.com/Kotlin/kotlinx.coroutines#using-in-your-projects).
39
403. Open the `Main.kt` file in `src/main/kotlin`.
41
42    The `src` directory contains Kotlin source files and resources. The `Main.kt` file contains sample code that will print `Hello World!`.
43
444. Create the `simple()` function that returns a flow of three numbers:
45
46    * 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.
47    * 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.
48
49    ```kotlin
50    import kotlinx.coroutines.*
51    import kotlinx.coroutines.flow.*
52    import kotlin.system.*
53
54    fun simple(): Flow<Int> = flow {
55        for (i in 1..3) {
56            delay(100)
57            emit(i)
58        }
59    }
60    ```
61
625. Change the code in the `main()` function:
63
64    * Use the [`runBlocking()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) block to wrap a coroutine.
65    * Collect the emitted values using the [`collect()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/collect.html) function.
66    * 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.
67    * Print the collected value from the flow using the [`println()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/println.html) function.
68
69    ```kotlin
70    fun main() = runBlocking {
71        simple()
72            .collect { value ->
73                delay(300)
74                println(value)
75            }
76    }
77    ```
78
796. Build the code by clicking **Build Project**.
80
81    ![Build an application](flow-build-project.png)
82
83## Debug the coroutine
84
851. Set a breakpoint at the line where the `emit()` function is called:
86
87    ![Build a console application](flow-breakpoint.png)
88
892. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
90
91    ![Build a console application](flow-debug-project.png)
92
93    The **Debug** tool window appears:
94    * The **Frames** tab contains the call stack.
95    * The **Variables** tab contains variables in the current context. It tells us that the flow is emitting the first value.
96    * The **Coroutines** tab contains information on running or suspended coroutines.
97
98    ![Debug the coroutine](flow-debug-1.png)
99
1003. Resume the debugger session by clicking **Resume Program** in the **Debug** tool window. The program stops at the same breakpoint.
101
102    ![Debug the coroutine](flow-resume-debug.png)
103
104    Now the flow emits the second value.
105
106    ![Debug the coroutine](flow-debug-2.png)
107
108### Optimized-out variables
109
110If you use `suspend` functions, in the debugger, you might see the "was optimized out" text next to a variable's name:
111
112![Variable "a" was optimized out](variable-optimised-out.png)
113
114This text means that the variable's lifetime was decreased, and the variable doesn't exist anymore.
115It is difficult to debug code with optimized variables because you don't see their values.
116You can disable this behavior with the `-Xdebug` compiler option.
117
118> __Never use this flag in production__: `-Xdebug` can [cause memory leaks](https://youtrack.jetbrains.com/issue/KT-48678/Coroutine-debugger-disable-was-optimised-out-compiler-feature#focus=Comments-27-6015585.0-0).
119>
120{style="warning"}
121
122## Add a concurrently running coroutine
123
1241. Open the `Main.kt` file in `src/main/kotlin`.
125
1262. Enhance the code to run the emitter and collector concurrently:
127
128    * 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.
129
130    ```kotlin
131    fun main() = runBlocking<Unit> {
132        simple()
133            .buffer()
134            .collect { value ->
135                delay(300)
136                println(value)
137            }
138    }
139    ```
140
1413. Build the code by clicking **Build Project**.
142
143## Debug a Kotlin flow with two coroutines
144
1451. Set a new breakpoint at `println(value)`.
146
1472. Run the code in debug mode by clicking **Debug** next to the run configuration at the top of the screen.
148
149    ![Build a console application](flow-debug-3.png)
150
151    The **Debug** tool window appears.
152
153    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.
154    The `buffer()` function buffers emitted values from the flow.
155    The emitter coroutine has the **RUNNING** status, and the collector coroutine has the **SUSPENDED** status.
156
1573. Resume the debugger session by clicking **Resume Program** in the **Debug** tool window.
158
159    ![Debugging coroutines](flow-debug-4.png)
160
161    Now the collector coroutine has the **RUNNING** status, while the emitter coroutine has the **SUSPENDED** status.
162
163    You can dig deeper into each coroutine to debug your code.
164