Launch and Async in Kotlin Coroutines in Kotlin
Kotlin coroutines simplify asynchronous programming with the launch and async builders. The launch launches a background coroutine for non-blocking tasks, while async is used for asynchronous operations that return results. Both offer concise syntax and structured concurrency, enhancing code readability.
Launch Function in Kotlin
In Kotlin, the launch function, part of kotlinx.coroutines, facilitates fire-and-forget operations by initiating non-blocking coroutines without returning an immediate result. It returns a Job reference, enabling the cancellation of the running coroutine.
Example:
Output:
Explanation:
-
The coroutine is launched using GlobalScope.launch.
-
Inside the coroutine, there's a simulated asynchronous work using delay(1000) for 1000 milliseconds.
-
While the coroutine is waiting, the println("Coroutine completed") statement is executed after the delay.
-
The runBlocking block is used to wait for the coroutine to finish, ensuring that the program doesn't terminate before the coroutine completes.
When to Use Launch?
The launch coroutine builder in Kotlin is used when you want to initiate a coroutine for a fire-and-forget operation. It's particularly suitable when you don't need an immediate result from the coroutine, and you're mainly interested in starting a background task. Here are common scenarios for using launch:
-
Fire-and-Forget Tasks: When you have a task or operation that doesn't return a result immediately, such as logging, event processing, or other background activities.
-
Parallel Execution: When you want to execute multiple tasks concurrently without waiting for their completion. launch allows for launching coroutines concurrently, enhancing parallelism.
-
Background Operations: In scenarios where you need to perform background work or asynchronous tasks without blocking the main thread, such as network requests or I/O operations.
Async Function in Kotlin
The async function serves as a mechanism to initiate a new coroutine, explicitly providing a Deferred object that signifies the eventual outcome of the computation. This construct is particularly well-suited for scenarios involving concurrent computations, where the objective is to obtain a result or combine multiple results at a later point. The Deferred object plays a crucial role by allowing the coroutine to pause its execution through the use of the await() function until the result is ready, thereby facilitating the seamless integration of asynchronous operations within the overall workflow.
Output:
Explanation:
-
In the given example, two asynchronous operations are started using async.
-
Each operation involves simulating some work, facilitated by the delay function, introducing a time delay to imitate asynchronous tasks.
-
The await() function is employed to explicitly wait for and retrieve the results of both asynchronous operations.
-
The output showcases the combined results obtained from the asynchronous tasks, consolidating the outcomes of the simulated work in a single display.
When to Use Async?
-
Parallel Network Calls: Use async when making multiple network calls concurrently but need to wait for all responses before proceeding with further computations.
-
Waiting for Results: async is suitable for scenarios where you want to await the results from multiple tasks running in parallel, ensuring that you have all the necessary information before proceeding.
-
Differentiating from Launch: It's crucial to note that while async can be used for parallel tasks, its distinctive feature is the ability to explicitly await results. If results are not awaited, it behaves similarly to launch for fire-and-forget operations.
Difference between Launch and Async
| launch{} | async{} |
|---|---|
| launch{} is designed for a "fire and forget" approach, where the coroutine is initiated without waiting for any result. | async{} is utilized to perform a specific task and explicitly return a result through the await() function. |
| The launch{} coroutine does not yield any return value as it follows a "fire and forget" paradigm, initiating the task without waiting for its completion. | the async{} coroutine is structured to return a result through the await() function, allowing the program to capture and utilize the outcome of the asynchronous operation. |
| launch{} is not suitable for parallel network calls as it is not designed to handle concurrent execution of tasks. | async{} is specifically designed for parallel execution of network calls, making it suitable for scenarios where concurrent operations are required. |
| launch{} doesn't block the main thread, allowing code to continue without waiting for the coroutine to finish. | async{} blocks the main thread at await(), making other code segments wait for the result. |
| launch{} is not a suspend call, meaning it does not introduce a pause in the program's execution. | async{} uses await() for suspension. |
| launch{} is suitable when the result is not needed | async{} is appropriate when results from multiple tasks that run in parallel are required. |
| launch{} is suitable for tasks like updating or changing color, where the result may not be crucial to the main execution. | async{} is useful for scenarios such as fetching data from two users through parallel network calls, where the results are needed for further computation. |
Examples of Launch and Aysnc
Example using launch{}:
Output:
Explanation :
-
The GlobalScope.launch launches a coroutine asynchronously, executing the code block inside it.
-
The main program proceeds without waiting for the launched coroutine to complete.
-
It prints "End of the program."
-
The program may exit before the launched coroutine finishes, so the "Executing task in launch{ }" may not be printed.
Example using async{}:
Output:
Explanation:
-
async{} concurrently fetches data for users 1 and 2.
-
The program continues without waiting for task completion.
-
await() is used to gather task results for further processing.
-
The program prints "Start of the program," processes data with await(), and prints "End of the program."
Conclusion
-
Kotlin coroutines, utilizing launch and async, simplify asynchronous programming with concise syntax and enhanced readability.
-
launch is for fire-and-forget tasks, initiating non-blocking coroutines without immediate result return.
-
Launch is ideal for non-blocking background tasks and parallel execution, prioritizing immediate completion is not crucial.
-
async explicitly initiates coroutines with a Deferred object, ideal for concurrent computations and result gathering.
-
async can be utilized for concurrent computations and explicit result gathering through await().