Вы решили свою непосредственную проблему, добавив зависимость, но позвольте мне добавить примечание о вашем использовании GlobalScope
.
Использование GlobalScope
в рабочем коде является антипаттерном.Это делается по тем же причинам, что и runBlocking
, чтобы облегчить проведение быстрых экспериментов.Вам особенно следует избегать этого на Android из-за сложного жизненного цикла компонентов приложения.
Если вы запускаете сопрограмму из обработчика событий Android, вы должны использовать текущую активность в качестве ее области сопрограммы.Это гарантирует, что ваша сопрограмма будет отменена, когда активность будет уничтожена.Без этого сопрограмма продолжится, ссылаясь на уже мертвую активность.
Вот пример, адаптированный из документации по CoroutineScope
, он показывает, как использовать вашу деятельность в качестве сопрограммы.область действия:
class MyActivity : AppCompatActivity(), CoroutineScope {
// Sets up the default dispatcher and the root job that we can use to centrally
// cancel all coroutines. We use SupervisorJob to avoid spreading the failure
// of one coroutine to all others.
override val coroutineContext: CoroutineContext =
Dispatchers.Main + SupervisorJob()
override fun onDestroy() {
super.onDestroy()
coroutineContext[Job]!!.cancel()
}
// this.launch picks up coroutineContext for its context:
fun loadDataFromUI() = this.launch {
// Switch to the IO dispatcher to perform blocking IO:
val ioData = withContext(Dispatchers.IO) {
// blocking I/O operations
}
draw(ioData) // use the data from IO to update UI in the main thread
}
}
Если вы используете ViewModel
, используйте его в качестве области действия и отмените основную работу с onClear
.
Если вы выполняете работу сфоновое задание, используйте вашу реализацию JobService
в качестве области действия и используйте onStartJob
и onStopJob
так, как мы используем onCreate
и onDestroy
выше.