Coroutines in Kotlin are lightweight threads with support for pausing and resuming computations without blocking OS threads. They are launched through functions such as launch, async when there is a parent CoroutineScope.
Dispatching occurs via CoroutineDispatcher objects, which define the thread/executor in which the coroutine is executed (Dispatchers.Main, Dispatchers.IO, Dispatchers.Default).
Example:
fun main() = runBlocking { launch(Dispatchers.IO) { val data = getDataFromNetwork() withContext(Dispatchers.Main) { updateUI(data) } } }
Cancellation: Coroutines are canceled by canceling their job/Scope, which throws an internal CancellationException. Coroutines should periodically check the cancellation flag or call suspending functions to terminate correctly.
Error handling: Exceptions in coroutines can "sink" — for example, if you don't handle an error in a child coroutine, it will just finish its execution, and the parent will remain unaware of the issue. There are mechanisms like SupervisorJob and CoroutineExceptionHandler for this purpose.
Nuances of context passing:
What will happen if one of the child coroutines inside a parent coroutine fails with an error while others continue to run? Will all children be canceled?
Many mistakenly believe that the error "stays in the child".
Correct answer: If a regular Job (or launch) is used, then all child coroutines are automatically canceled upon any child's error. To prevent child coroutines from being canceled, SupervisorJob or supervisorScope is used:
supervisorScope { launch { error("fail") } launch { println("This code will execute") } }
Story
Improper error handling — flow crash: In the project, coroutines were used to load data. Exceptions "sank" within child coroutines, causing the retry/recovery level not to work, and the main screen remained empty without any error messages for the user.
Story
UI freeze due to working with Dispatchers.Main: A young Android developer launched a heavy computation task on Dispatchers.Main — the UI started to "freeze". There was no understanding that any heavy computations should be executed on Dispatchers.Default or Dispatchers.IO.
Story
AbortError when canceling parent scope: One of the developers did not consider that when the parent scope is canceled, all child coroutines are completed with cancellation, and a critically important operation (data saving) was not completed.