[Kotlin coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html)enable you to write clean, simplified asynchronous code that keeps your app responsive while managing long-running tasks such as network calls or disk operations.

This topic provides a detailed look at coroutines on Android. If you're unfamiliar with coroutines, be sure to read[Kotlin coroutines on Android](https://developer.android.com/kotlin/coroutines)before reading this topic.

## Manage long-running tasks

Coroutines build upon regular functions by adding two operations to handle long-running tasks. In addition to`invoke`(or`call`) and`return`, coroutines add`suspend`and`resume`:

- `suspend`pauses the execution of the current coroutine, saving all local variables.
- `resume`continues execution of a suspended coroutine from the place where it was suspended.

You can call`suspend`functions only from other`suspend`functions or by using a coroutine builder such as`launch`to start a new coroutine.

The following example shows a simple coroutine implementation for a hypothetical long-running task:  

    suspend fun fetchDocs() {                             // Dispatchers.Main
        val result = get("https://developer.android.com") // Dispatchers.IO for `get`
        show(result)                                      // Dispatchers.Main
    }

    suspend fun get(url: String) = withContext(Dispatchers.IO) { /* ... */ }

In this example,`get()`still runs on the main thread, but it suspends the coroutine before it starts the network request. When the network request completes,`get`resumes the suspended coroutine instead of using a callback to notify the main thread.

Kotlin uses a*stack frame*to manage which function is running along with any local variables. When suspending a coroutine, the current stack frame is copied and saved for later. When resuming, the stack frame is copied back from where it was saved, and the function starts running again. Even though the code might look like an ordinary sequential blocking request, the coroutine ensures that the network request avoids blocking the main thread.

## Use coroutines for main-safety

Kotlin coroutines use*dispatchers* to determine which threads are used for coroutine execution. To run code outside of the main thread, you can tell Kotlin coroutines to perform work on either the*Default* or*IO*dispatcher. In Kotlin, all coroutines must run in a dispatcher, even when they're running on the main thread. Coroutines can suspend themselves, and the dispatcher is responsible for resuming them.

To specify where the coroutines should run, Kotlin provides three dispatchers that you can use:

- **Dispatchers.Main** - Use this dispatcher to run a coroutine on the main Android thread. This should be used only for interacting with the UI and performing quick work. Examples include calling`suspend`functions, running Android UI framework operations, and updating[`LiveData`](https://developer.android.com/topic/libraries/architecture/livedata)objects.
- **Dispatchers.IO** - This dispatcher is optimized to perform disk or network I/O outside of the main thread. Examples include using the[Room component](https://developer.android.com/topic/libraries/architecture/room), reading from or writing to files, and running any network operations.
- **Dispatchers.Default**- This dispatcher is optimized to perform CPU-intensive work outside of the main thread. Example use cases include sorting a list and parsing JSON.

Continuing the previous example, you can use the dispatchers to re-define the`get`function. Inside the body of`get`, call`withContext(Dispatchers.IO)`to create a block that runs on the IO thread pool. Any code you put inside that block always executes via the`IO`dispatcher. Since`withContext`is itself a suspend function, the function`get`is also a suspend function.  

    suspend fun fetchDocs() {                      // Dispatchers.Main
        val result = get("developer.android.com")  // Dispatchers.Main
        show(result)                               // Dispatchers.Main
    }

    suspend fun get(url: String) =                 // Dispatchers.Main
        withContext(Dispatchers.IO) {              // Dispatchers.IO (main-safety block)
            /* perform network IO here */          // Dispatchers.IO (main-safety block)
        }                                          // Dispatchers.Main
    }

With coroutines, you can dispatch threads with fine-grained control. Because`withContext()`lets you control the thread pool of any line of code without introducing callbacks, you can apply it to very small functions like reading from a database or performing a network request. A good practice is to use`withContext()`to make sure every function is*main-safe*, which means that you can call the function from the main thread. This way, the caller never needs to think about which thread should be used to execute the function.

In the previous example,`fetchDocs()`executes on the main thread; however, it can safely call`get`, which performs a network request in the background. Because coroutines support`suspend`and`resume`, the coroutine on the main thread is resumed with the`get`result as soon as the`withContext`block is done.
| **Important:** Using`suspend`doesn't tell Kotlin to run a function on a background thread. It's normal for`suspend`functions to operate on the main thread. It's also common to launch coroutines on the main thread. You should always use`withContext()`inside a`suspend`function when you need main-safety, such as when reading from or writing to disk, performing network operations, or running CPU-intensive operations.

### Performance of withContext()

[`withContext()`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html)does not add extra overhead compared to an equivalent callback-based implementation. Furthermore, it's possible to optimize`withContext()`calls beyond an equivalent callback-based implementation in some situations. For example, if a function makes ten calls to a network, you can tell Kotlin to switch threads only once by using an outer`withContext()`. Then, even though the network library uses`withContext()`multiple times, it stays on the same dispatcher and avoids switching threads. In addition, Kotlin optimizes switching between`Dispatchers.Default`and`Dispatchers.IO`to avoid thread switches whenever possible.
| **Important:** Using a dispatcher that uses a thread pool like`Dispatchers.IO`or`Dispatchers.Default`does not guarantee that the block executes on the same thread from top to bottom. In some situations, Kotlin coroutines might move execution to another thread after a`suspend`-and-`resume`. This means thread-local variables might not point to the same value for the entire`withContext()`block.

## Start a coroutine

You can start coroutines in one of two ways:

- [`launch`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html)starts a new coroutine and doesn't return the result to the caller. Any work that is considered "fire and forget" can be started using`launch`.
- [`async`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html)starts a new coroutine and allows you to return a result with a suspend function called`await`.

Typically, you should`launch`a new coroutine from a regular function, as a regular function cannot call`await`. Use`async`only when inside another coroutine or when inside a suspend function and performing parallel decomposition.
| **Warning:** `launch`and`async`handle exceptions differently. Since`async`expects an eventual call to`await`, it holds exceptions and rethrows them as part of the`await`call. This means if you use`async`to start a new coroutine from a regular function, you might silently drop an exception. These dropped exceptions won't appear in your crash metrics or be noted in logcat. For more information, see[Cancellation and Exceptions in Coroutines](https://medium.com/androiddevelopers/cancellation-in-coroutines-aa6b90163629).

### Parallel decomposition

All coroutines that are started inside a`suspend`function must be stopped when that function returns, so you likely need to guarantee that those coroutines finish before returning. With*structured concurrency* in Kotlin, you can define a`coroutineScope`that starts one or more coroutines. Then, using`await()`(for a single coroutine) or`awaitAll()`(for multiple coroutines), you can guarantee that these coroutines finish before returning from the function.

As an example, let's define a`coroutineScope`that fetches two documents asynchronously. By calling`await()`on each deferred reference, we guarantee that both`async`operations finish before returning a value:  

    suspend fun fetchTwoDocs() =
        coroutineScope {
            val deferredOne = async { fetchDoc(1) }
            val deferredTwo = async { fetchDoc(2) }
            deferredOne.await()
            deferredTwo.await()
        }

You can also use`awaitAll()`on collections, as shown in the following example:  

    suspend fun fetchTwoDocs() =        // called on any Dispatcher (any thread, possibly Main)
        coroutineScope {
            val deferreds = listOf(     // fetch two docs at the same time
                async { fetchDoc(1) },  // async returns a result for the first doc
                async { fetchDoc(2) }   // async returns a result for the second doc
            )
            deferreds.awaitAll()        // use awaitAll to wait for both network requests
        }

Even though`fetchTwoDocs()`launches new coroutines with`async`, the function uses`awaitAll()`to wait for those launched coroutines to finish before returning. Note, however, that even if we had not called`awaitAll()`, the`coroutineScope`builder does not resume the coroutine that called`fetchTwoDocs`until after all of the new coroutines completed.

In addition,`coroutineScope`catches any exceptions that the coroutines throw and routes them back to the caller.

For more information on parallel decomposition, see[Composing suspending functions](https://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html).

## Coroutines concepts

### CoroutineScope

A[`CoroutineScope`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/)keeps track of any coroutine it creates using`launch`or`async`. The ongoing work (i.e. the running coroutines) can be cancelled by calling`scope.cancel()`at any point in time. In Android, some KTX libraries provide their own`CoroutineScope`for certain lifecycle classes. For example,`ViewModel`has a[`viewModelScope`](https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#(androidx.lifecycle.ViewModel).viewModelScope:kotlinx.coroutines.CoroutineScope), and`Lifecycle`has[`lifecycleScope`](https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#lifecyclescope). Unlike a dispatcher, however, a`CoroutineScope`doesn't run the coroutines.
| **Note:** For more information about`viewModelScope`, see[Easy Coroutines in Android: viewModelScope](https://medium.com/androiddevelopers/easy-coroutines-in-android-viewmodelscope-25bffb605471).

`viewModelScope`is also used in the examples found in[Background threading on Android with Coroutines](https://developer.android.com/kotlin/coroutines). However, if you need to create your own`CoroutineScope`to control the lifecycle of coroutines in a particular layer of your app, you can create one as follows:  

    class ExampleClass {

        // Job and Dispatcher are combined into a CoroutineContext which
        // will be discussed shortly
        val scope = CoroutineScope(Job() + Dispatchers.Main)

        fun exampleMethod() {
            // Starts a new coroutine within the scope
            scope.launch {
                // New coroutine that can call suspend functions
                fetchDocs()
            }
        }

        fun cleanUp() {
            // Cancel the scope to cancel ongoing coroutines work
            scope.cancel()
        }
    }

A cancelled scope cannot create more coroutines. Therefore, you should call`scope.cancel()`only when the class that controls its lifecycle is being destroyed. When using`viewModelScope`, the[`ViewModel`](https://developer.android.com/topic/libraries/architecture/viewmodel)class cancels the scope automatically for you in the ViewModel's`onCleared()`method.

### Job

A[`Job`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html)is a handle to a coroutine. Each coroutine that you create with`launch`or`async`returns a`Job`instance that uniquely identifies the coroutine and manages its lifecycle. You can also pass a`Job`to a`CoroutineScope`to further manage its lifecycle, as shown in the following example:  

    class ExampleClass {
        ...
        fun exampleMethod() {
            // Handle to the coroutine, you can control its lifecycle
            val job = scope.launch {
                // New coroutine
            }

            if (...) {
                // Cancel the coroutine started above, this doesn't affect the scope
                // this coroutine was launched in
                job.cancel()
            }
        }
    }

### CoroutineContext

A[`CoroutineContext`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html)defines the behavior of a coroutine using the following set of elements:

- [`Job`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html): Controls the lifecycle of the coroutine.
- [`CoroutineDispatcher`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html): Dispatches work to the appropriate thread.
- [`CoroutineName`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-name/index.html): The name of the coroutine, useful for debugging.
- [`CoroutineExceptionHandler`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html): Handles uncaught exceptions.

For new coroutines created within a scope, a new`Job`instance is assigned to the new coroutine, and the other`CoroutineContext`elements are inherited from the containing scope. You can override the inherited elements by passing a new`CoroutineContext`to the`launch`or`async`function. Note that passing a`Job`to`launch`or`async`has no effect, as a new instance of`Job`is always assigned to a new coroutine.  

    class ExampleClass {
        val scope = CoroutineScope(Job() + Dispatchers.Main)

        fun exampleMethod() {
            // Starts a new coroutine on Dispatchers.Main as it's the scope's default
            val job1 = scope.launch {
                // New coroutine with CoroutineName = "coroutine" (default)
            }

            // Starts a new coroutine on Dispatchers.Default
            val job2 = scope.launch(Dispatchers.Default + CoroutineName("BackgroundCoroutine")) {
                // New coroutine with CoroutineName = "BackgroundCoroutine" (overridden)
            }
        }
    }

| **Note:** For more information about[`CoroutineExceptionHandler`](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-exception-handler/index.html), see[exceptions in coroutines blog post](https://medium.com/androiddevelopers/exceptions-in-coroutines-ce8da1ec060c).

## Additional coroutines resources

For more coroutines resources, see the following links:

- [Kotlin coroutines on Android](https://developer.android.com/kotlin/coroutines)
- [Additional resources for Kotlin coroutines and flow](https://developer.android.com/kotlin/coroutines/additional-resources)