So far as I can make out the following is a very common pattern for enabling coroutines in Android ViewModels.
class CoroutineScopedViewModel : ViewModel(), CoroutineScope {
private val _job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + _job
override fun onCleared() {
super.onCleared()
_job.cancel()
}
fun thisIsCalledFromDataBoundView() = launch {
/* do some UI */
withContext(Dispatchers.IO) {
try {
/* do some IO */
} catch (error: IOException) {
/* do some exception handling */
}
}
}
}
Before I go about refactoring my project from the experimental (pre-1.0.0) version, I need to just have something clarified:
If the activity or fragment attached to the viewmodel is closed before the withContext(Dispatchers.IO) block is completed will that child job be canceled before completing? I.e. can this model be used for inserting data into my DB, or could some strange timing issue arise where the user hits back or otherwise causes the ViewModel owner to close that ends up losing the data?
To be clear I currently use GlobalScope.launch(Dispatchers.IO)
(quickest conversion from 1.2.7x to 1.3.x) to write user entries into the SQLite DB (that I later sync with a server in the background), I just don;t want to inadvertently introduce a timing bug because I misunderstood something and converted to the model shown above.