How suspend and resume works on coroutines in android

Viewed 2857

I am learning co-routines

I have a sample from developer docs

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 the example above, 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.


What I understand: Co routines suspend the long running operations from main thread and once the long running operations complete ... they resume instead of giving a callback and without blocking the main thread


Question: What happens when in screen one, I suspend the code and before it resumes I navigate the screen two.

2 Answers

The operation on Dispatcher.IO will continue and on its completion the coroutine will run on Dispatcher.Main

You will need to handle Android Activity/Fragment lifecycle before invoking show(result) assuming that you are doing UI operations in this method.

To Handle the scenario you mentioned i.e switch to other screen before the coroutines completes its work, there are couple of approaches you can implement:

  1. ViewmodelScope : You can follow MVVM architecture where you will be launching the coroutine written in repository class from viewmodel in viewModelScope. The trick here is inside the viewmodel , you will have access to viewmodelScope which will clears off all the child coroutines whenever viewmodel lifecycle ends i.e fragment's onDestroyed -> viewmodel's onCleared() invokes. example:

// function in viewmodel looks like

fun fetchDocs() {
    viewModelScope.launch {
        repository.get();
    }
}

2. Scope cancelling :You can create the scope and launch your coroutines inside it. when you want to cancel the coroutine , simply cancel the scope and it will cancel all its children coroutines. example:

private val uiScope = CoroutineScope(Job() + Dispatchers.Main)
    uiScope.launch {
      repository.get();
    }
}

// cancel scope
uiScope.cancel()

A good explanation on how to handle coroutines can be found at this Blog

Related