Если у вас есть асинхронный работник, жизненный цикл которого действительно глобален (они умирают / заканчиваются, когда ваш процесс умирает), то можно использовать GlobalScope
или аналогичную область действия на всю жизнь, это нормально.
Скажем, у вас есть активность, которая делает запрос, но фактический сетевой запрос должен продолжаться, даже если активность уходит, потому что вы хотели бы кэшировать его, когда сеть, наконец, вернет ответ.
Вы добавите CoroutineScope
к вашей Деятельности / Фрагменту или лучше к вашей ViewModel и получите свой код, который, наконец, помещает материал на экран в этой области.Когда Activity / Fragment / ViewModel умирает, область действия отменяется, и на экране больше не будет попытки показать что-то, что больше не существует.
Однако ваша Fragment / Activity / ViewModel может общаться с источником данных./ репозиторий, жизненный цикл которого заканчивается только после завершения процесса.Вы можете переключиться на GlobalScope там , чтобы ваши сетевые ответы кэшировались, даже когда ни одна Activity / Fragment / ViewModel не активна, чтобы показать результат на экране.
class MyViewModel(context: CoroutineContext, repo: MyRepository) : ViewModel() {
private val scope: CoroutineScope(context + SuperviserJob())
override fun onCleared() { scope.cancel() }
fun getDataFromNetwork() {
scope.launch {
myLiveData.value = repo.getDataFromNetwork()
}
}
}
// Singleton class
class MyRepositoryImpl(context: CoroutineContext) : MyRepository {
private val scope: CoroutineScope(context + SupervisorJob())
override suspend fun getDataFromNetwork() : String {
return scope.async { // switch scopes
val data = ... fetch data ...
saveInCache(data)
}.await()
}
}
Когда ваша ViewModel заканчивается (вызывается onCleared
), MyRepositoryImpl
getDataFromNetwork
продолжает работать и будет вызывать saveInCache
, если все пойдет правильно.Однако возвращенное значение не будет присвоено myLiveData.value
, поскольку сопрограмма области видимости вашей модели ViewModel была отменена.