1 – Introduction
When working with coroutines in Kotlin , there are utility methods and execution methods that help you manage asynchronous tasks efficiently. These methods are essential tools for controlling:
- The execution time of the tasks.
- The context in which tasks are performed.
- Starting and synchronizing multiple coroutines .
In this article, we will explore the most important methods, such as withTimeout
, withContext
, launch
, async
, and others, with practical examples to understand how and when to use them.
2 – Utility Methods
2.1 – withTimeout
- What is it? Cancels the execution of a block of code if the timeout is reached.
- When to use? To prevent asynchronous tasks from getting stuck indefinitely.
- Example:
import kotlinx.coroutines.*
fun main( ) = runBlocking{
try {
withTimeout ( 1000) { // 1 second timeout
delay( 2000) // Simulates a long task
println ( "Task completed!")
}
} catch (e: TimeoutCancellationException ) {
println ( "Timeout reached! Task canceled.")
}
}
2.2 - withTimeoutOrNull
-
What is it?
Similar to
withTimeout
, but instead of throwing an exception, it returns null if the timeout is reached. - When to use? To avoid using exceptions and handle timeout in a more controlled way.
- Example:
import kotlinx.coroutines.*
fun main() = runBlocking {
val result = withTimeoutOrNull(1000) { // 1 second timeout
delay(2000) // Simulates a long task
"Job completed!"
}
if (result == null) {
println("Timeout reached! Returned null .")
} else {
println(result)
}
}
2.3 – withContext
- What is it? Changes the context of the coroutine (e.g.: changes the dispatcher ).
- When to use? temporarily change the dispatcher within a coroutine .
- Example:
import kotlinx.coroutines .*
fun main() = runBlocking {
println(" Running on Default Dispatcher : ${Thread.currentThread().name}")
withContext(Dispatchers.IO) {
println(" Running in IO Dispatcher: ${Thread.currentThread().name}")
}
println("Back to Default Dispatcher : ${Thread.currentThread().name}")
}
2.4 – delay
- What is it? Suspends the execution of a coroutine for a period of time, without blocking the thread.
- When to use? To simulate time-consuming tasks or wait for a response.
- Example:
import kotlinx.coroutines.*
fun main() = runBlocking {
println("Starting task...")
delay(1000) // Suspend for 1 second
println("Task completed!")
}
2.5 – yield
- What is it? Yields the current context, allowing other coroutines to run.
- When to use? To improve cooperation between coroutines and avoid unnecessary blocking.
- Example:
import kotlinx.coroutines.*
fun main() = runBlocking{
launch {
repeat(3) { i ->
println(" Coroutine 1 - Iteration $i")
yield() // Yield the context
}
}
launch {
repeat(3) { i ->
println(" Coroutine 2 - Iteration $i")
yield() // Yield the context
}
}
}
3 – Execution Methods
3.1 – launch
- What is it? Creates a new coroutine and starts its execution immediately.
- When to use? When you don't need to return a result from the coroutine .
- Example:
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
println("Coroutine started!")
delay(1000)
println("Coroutine finished!")
}
}
3.2 – async
- What is it? Creates a new coroutine that returns a value (deferred).
- When to use? For asynchronous tasks that return results.
- Example:
import kotlinx.coroutines.*
fun main() = runBlocking {
val result = async {
delay(1000)
"Result calculated!"
}
println("Waiting for result...")
println("Result:${result.await()}")
}
3.3 – runBlocking
- What is it? Executes coroutines in a blocking function.
- When to use? Only in specific cases, such as small scripts or for quick testing.
- Example:
import kotlinx.coroutines.*
fun main( ) = runBlocking {
println("Starting runBlocking")
delay(1000)
println("Finalizing runBlocking")
}
4 – Comparison: Utility Methods vs. Execution Methods
Aspect | Utility Methods | Execution Methods |
---|---|---|
Main Function | Control time, context, and suspension. | Start and manage coroutines. |
Return Value | Generally, they do not return values. | Some return values (e.g. async ). |
Main Examples |
withTimeout , delay , yield
|
launch , async , runBlocking
|
5 – Conclusion
Utility and runner methods are indispensable tools in the Kotlin coroutine ecosystem. They allow you to control asynchronous execution in a precise, scalable, and efficient way.
Summary of Methods:
1. Utilities:
-
Timeout control:
withTimeout
,withTimeoutOrNull
. -
Context:
withContext
. -
Suspension:
delay
,yield
.
2. Execution:
-
launch
for coroutines that do not return values. -
async
for coroutines that return results. -
runBlocking
to run coroutines in scripts or simple tests.
In the next article, we will explore how to efficiently test coroutines and flows with native tools and libraries like Turbine.