launchWhenCreated() vs launchWhenStarted() vs launchWhenResumed() vs repeatOnLifeCycle()
Tags: android, kotlin, beginners, jetpackcompose
Published: 2022-12-23 23:00:00

**Investigating and experimenting various LifecycleCoroutineScope launchWhenX() and repeatOnLifeCycle() functions**

This is part of the Kotlin coroutines series:
* [Part 1 - Kotlin Coroutines Basics - Simple Android App Demo](https://vtsen.hashnode.dev/kotlin-coroutines-basics-simple-android-app-demo)    
* [Part 2 - kotlinx.coroutines.delay() vs Thread.sleep()](https://vtsen.hashnode.dev/kotlinxcoroutinesdelay-vs-threadsleep)   
* [Part 3 - GlobalScope vs viewModelScope vs lifecycleScope vs rememberCoroutineScope](https://vtsen.hashnode.dev/globalscope-vs-viewmodelscope-vs-lifecyclescope-vs-remembercoroutinescope)    
* **Part 4 - launchWhenCreated() vs launchWhenStarted() vs launchWhenResumed() vs repeatOnLifeCycle()**

In the previous article, we learned about [LifeCycleCoroutineScope.launch()](https://vtsen.hashnode.dev/globalscope-vs-viewmodelscope-vs-lifecyclescope-vs-remembercoroutinescope#heading-lifecyclescopelaunch). However, there are a few additional functions in `LifeCycleCoroutineScope`:

*   `launchWhenCreated()`
    
*   `launchWhenStarted()`
    
*   `launchWhenResumed()`
    

## launchWhenX()

The code usage looks like this:

```kotlin
@Composable  
fun DemoScreen() {  
 
    val lifeCycleScope = LocalLifecycleOwner.current.lifecycleScope
     
    Button(onClick = {  
        lifeCycleScope.launchWhenStarted {
           /*...*/
        }
    }) 
}
```

The benefit of using this `launchWhenX()` APIs is it can automatically start, suspend and resume the coroutines for you. The table below shows you in what lifecycle event, the coroutines are started, suspended, resumed and canceled.

| launchWhenX functions | When coroutines are started? | When coroutines are suspended? | When coroutines are resumed? | When coroutines cancelled? |
| --- | --- | --- | --- | --- |
| launchWhenCreated() | ON\_CREATE | N/A | N/A | ON\_DESTROY |
| launchWhenStarted() | ON\_START | ON\_STOP | ON\_START | ON\_DESTROY |
| launchWhenResumed() | ON\_RESUME | ON\_PAUSE | ON\_RESUME | ON\_DESTROY |

> Depends on when you call `launchWhenX()`, it automatically starts the coroutine when your current lifecycle state equals or above the target `X` lifecycle state.

The issue with `launchWhenCreated()` is when the lifecycle is destroyed, the `LifeCycleCoroutineScope` cancels all the coroutines. Since there are no more coroutines, there is nothing to be suspended or resumed.

To understand the lifecycle in detail, please read the following article:

- [Activity and View Model Lifecycles Demo App](https://vtsen.hashnode.dev/activity-and-view-model-lifecycles-demo-app)

Here is the summary of app visibility status corresponding to its lifecycle state:

| Lifecycle States | App Visibility Status |
| --- | --- |
| CREATED | NOT visible |
| STARTED | Visible at background |
| RESUMED | Visible at foreground |

Given all these functions above, it looks like `launchWhenStarted()` should be used because it doesn't waste any resources when your app is not visible. You can use `launchWhenResumed()`, but it suspends the coroutine when your app is still visible in the background, which we don't want.

## launchWhenStarted() vs repeatOnLifeCycle()

But, wait! Isn't `launchWhenStarted()` same as `repeatOnLifeCycle(Lifecycle.State.STARTED)`?

```kotlin
@Composable  
fun DemoScreen() {  
    val lifeCycle = LocalLifecycleOwner.current.lifecycle
    val lifeCycleScope = LocalLifecycleOwner.current.lifecycleScope
     
    Button(onClick = {  
        lifeCycleScope .launch {
            lifeCycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                /*...*/
            }
        }
    }) 
}
```

Here is a summary of `launchWhenStarted()` vs `repeatOnLifecycle(Lifecycle.State.STARTED)` comparisons:

| Launch Functions | When coroutines are started? | When coroutines are suspended? | When coroutines are resumed? | When coroutines are canceled? |
| --- | --- | --- | --- | --- |
| launchWhenStarted() | ON\_START | ON\_CREATE | START | ON\_DESTROY |
| repeatOnLifecycle(Lifecycle.State.STARTED) | ON\_START | N/A | N/A | ON\_STOP |

As you can see, `repeatOnLifecycle(Lifecycle.State.STARTED)` doesn't suspend or resume the coroutines. When the lifecycle state moves below the STARTED state, it cancels all the coroutines. When it moves to STARTED state again, it starts the coroutine again.

On the other hand, `launchWhenStarted()` doesn't cancel the coroutines, but it suspends the coroutines instead.

| Launch Functions | App Is Not Visible (ON\_STOP) | App Becomes Visible (ON\_START) |
| --- | --- | --- |
| launchWhenStarted() | Coroutines suspended | Coroutines resumed |
| repeatOnLifecycle(Lifecycle.State.STARTED) | Coroutines canceled | Coroutines started **again** |

In other words, what happens if the app moves to the background (app is not visible), then moves to the foreground (app is visible) again?

*   `launchWhenStarted()` suspends and resumes coroutines
    
*   `repeatOnLifecycle(Lifecycle.State.STARTED)` restarts the coroutines
    

If your coroutine count from 0 → 10000, `repeatOnLifecycle(Lifecycle.State.STARTED)` simply restarts the counter and starts from 0 again. Since `launchWhenStarted()` doesn't restart the coroutines, it appears it is the better option here.

## Conclusion

## Conclusion

Google advocates `repeatOnLifecycle(Lifecycle.State.STARTED)` over `launchWhenStarted()` because `launchWhenStarted()` is not safe to collect, it keeps emitting in the background when the UI is not visible. However, I don't see this behavior based on the experiment that I have done.

It seems to me both `launchWhenStarted()` and `repeatOnLifecycle(Lifecycle.State.STARTED)` are safe to collect. Depending on your need, `launchWhenStarted()` suspends and resumes the coroutine, and `repeatOnLifecycle(Lifecycle.State.STARTED)` restarts the coroutine.

You can also use them for collecting flow. See this article for details:

- [Exploring Different Ways to Collect Kotlin Flow](https://vtsen.hashnode.dev/exploring-different-ways-to-collect-kotlin-flow) 

## Source Code

GitHub Repository: [Demo\_CoroutineScope](https://github.com/vinchamp77/Demo_CoroutineScope)

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/launchwhencreated-vs-launchwhenstarted-vs-launchwhenresumed-vs-repeatonlifecycle)*.