Step #4: Wrapping the suspend Functions

RosterMotor still is showing an error message, where we cannot call save() on ToDoRepository because:

Suspend function 'save' should be called only from a coroutine or another suspend function

That is because you cannot call a suspend function from a normal function as we are doing here. Either:

To fix that, revise save() in RosterMotor to be:

  fun save(model: ToDoModel) {
    viewModelScope.launch {
      repo.save(model)
    }
  }

To consume a suspend function from a normal function, you can use launch on a CoroutineScope. In effect, launch says “I am willing to deal with suspend functions, allowing my work to be suspended as needed to wait for the suspend work to complete”.

As noted earlier, viewModelScope is aware of the viewmodel’s lifecycle. When the viewmodel is cleared (after the user exits the fragment), any outstanding coroutines being run in the context of the viewModelScope get canceled. For a read operation, that is fine. However, usually, we want a write operation to proceed even if the user moved along in the UI. That is why, in ToDoRepository, we are using the appScope CoroutineScope as a wrapper around the Room coroutines. appScope is set up to live for as long as our process does, so any coroutines executed from within it will get to run to completion, even if viewModelScope gets canceled.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.