Flow exception handling in Kotlin - Time & Space Complexity
When working with Kotlin Flows, handling exceptions properly is important to keep your app running smoothly.
We want to understand how adding exception handling affects the time it takes to process data in a flow.
Analyze the time complexity of the following code snippet.
val flow = flow {
for (i in 1..n) {
emit(i)
}
}.catch { e ->
emit(-1) // emit error value
}
flow.collect { value ->
println(value)
}
This code emits numbers from 1 to n, and if an exception happens, it emits -1 instead.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop inside the flow builder that emits values.
- How many times: It runs n times, once for each number from 1 to n.
- Exception handling: The catch block runs only if an error occurs, so it does not repeat with n.
As n grows, the number of emitted values grows linearly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 emits and collects |
| 100 | About 100 emits and collects |
| 1000 | About 1000 emits and collects |
Pattern observation: The work grows directly with n, so doubling n roughly doubles the work.
Time Complexity: O(n)
This means the time to process the flow grows in a straight line as the number of items increases.
[X] Wrong: "Adding exception handling makes the flow run slower for every item emitted."
[OK] Correct: The catch block only runs when an error happens, so normal emissions are not slowed down by exception handling.
Understanding how exception handling affects flow processing helps you write reliable and efficient Kotlin code, a skill valuable in many real projects.
"What if the flow used retry() to repeat on error? How would the time complexity change?"
Practice
catch operator in Kotlin Flow?Solution
Step 1: Understand the role of
Thecatchin Flowcatchoperator is designed to intercept exceptions that happen during the emission of values in a Flow.Step 2: Differentiate from other operators
Operators likemaptransform values,collectstarts the flow, andcancelstops it. Onlycatchhandles errors.Final Answer:
To handle exceptions that occur during the flow emission -> Option BQuick Check:
Flow error handling = catch [OK]
- Confusing catch with map or collect
- Thinking catch cancels the flow
- Assuming catch transforms values
Solution
Step 1: Recall the correct operator name
The operator to handle exceptions in Kotlin Flow iscatch, nottry,handle, orerror.Step 2: Verify the lambda syntax
The lambda receives the exceptioneand can emit fallback values inside it, matching the syntaxflow.catch { e -> emit(fallbackValue) }.Final Answer:
flow.catch { e -> emit(fallbackValue) } -> Option AQuick Check:
Correct catch syntax = flow.catch { e -> ... } [OK]
- Using try instead of catch
- Wrong operator names like handle or error
- Incorrect lambda parameter usage
import kotlinx.coroutines.flow.*
suspend fun main() {
flow {
emit(1)
throw RuntimeException("Error!")
}
.catch { emit(99) }
.collect { println(it) }
}Solution
Step 1: Analyze the flow emissions and exception
The flow emits 1, then throws a RuntimeException. Thecatchoperator catches this exception and emits 99 as a fallback.Step 2: Understand the collection output
The collector prints each emitted value. So it prints 1 first, then after catching the exception, it prints 99.Final Answer:
1 99 -> Option DQuick Check:
Emit before error + catch fallback = 1 and 99 [OK]
- Expecting exception message to print
- Thinking flow stops without catch
- Ignoring emitted values before error
flow {
emit(10)
throw IllegalStateException("Oops")
}.catch { e ->
println("Caught: $e")
}.collect {
println(it)
}Solution
Step 1: Review catch usage
Thecatchblock prints the exception but does not emit any fallback value, so the flow ends after the exception.Step 2: Understand flow continuation
Without emitting a fallback value insidecatch, the collector won't receive any value after the error, which might not be intended.Final Answer:
Missing emit inside catch to provide fallback value -> Option AQuick Check:
catch without emit = no fallback value [OK]
- Placing catch after collect
- Trying to collect inside catch
- Not emitting fallback value in catch
Solution
Step 1: Identify where exception occurs
flow { for (i in 1..3) { if (i == 2) throw Exception() emit(i) } }.catch { emit(-1) } throws an exception at i == 2, triggering the catch block to emit -1 as fallback.Step 2: Confirm fallback emission and completion
The catch block emits -1, then the flow completes. Codes without throwing an exception during the emission loop do not trigger catch. Code that rethrows the exception in catch does not emit fallback.Final Answer:
flow { for (i in 1..3) { if (i == 2) throw Exception() emit(i) } }.catch { emit(-1) } -> Option CQuick Check:
Throw inside flow + catch emit fallback = flow { for (i in 1..3) { if (i == 2) throw Exception() emit(i) } }.catch { emit(-1) } [OK]
- Not throwing exception inside emission loop
- Rethrowing exception in catch instead of emitting fallback
- Throwing exception outside emission range
Ready to prove it?
Pass the test and this pattern moves unknown
