There are libraries that actually help us do structured concurrency without having to write boilerplate in every ViewModel
. In order to use these libraries, we need to know the types of coroutine scopes that exist.
Coroutines in this scope are useful when there is work that should only be done when a ViewModel is active. To avoid boilerplate, add the code below to your build.gradle
file.
implementation “androidx.lifecycle:lifecycle-viewmodel-ktx:$view_model_scope_version”
This library adds viewModelScope
as an extension function and binds the scope to Dispatchers.Main
by default. However, the dispatcher can be changed if need be. The job is also automatically canceled when the ViewModel is cleared, so all we have to do is this:
class MainViewModel : ViewModel(){private fun doSomething(){viewModelScope.launch(Dispatchers.Default){ //Specify dispatcher if you like// Coroutine is launched. Time to do something.}}// No need to override onCleared, it's taken care of :)}
A LifecycleScope
is defined for each Lifecycle object. LifecycleOwner
could be an Activity or a Fragment. Any coroutine lanced in this scope is canceled when the Lifecycle is destroyed. You can access the Lifecycle’s CoroutineScope via lifecycle.coroutineScope
or lifecycleOwner.lifecycleScope
properties. To use this, add the following dependency to your build.gradle
file.
implementation “androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_scope_version”
Launching a coroutine using this scope can be done like this:
class HomeFragment: Fragment() {...private fun doSomething(){lifecycleOwner.lifecycleScope.launch {// Coroutine launched. Do some computation here.}}}
This is a lot cleaner than writing boilerplate when you want to launch a coroutine.