Котлиновские корутины — библиотека для асинхронного стиля программирования. Подробнее тут

Как их используем:

В базовый Presenter или ViewModel наследуем от CoroutineScope, создаем Job и переопределяем контекст корутин.

private val job = Job()

override val coroutineContext = job + Dispatchers.Main + SupervisorJob()

Далее в методе onCleared() во ViewModel или onDestroy() в Presenter завершаем корутину.

override fun onCleared() {
    job.complete()
    super.onCleared()
}

override fun onDestroy() {
    job.complete()
    super.onCleared()
}

Чтобы сделать асинхронный запрос в Presenter/ViewModel:

launch(ExceptionsHandler(exceptionsMapper)) {
    val data = withContext(Dispatchers.IO) { onboardingRepository.getOnboardingData() }
    items.value = data
}

launch — запуск корутины без блокировки текущего потока

ExceptionHandler — обработчик ошибок для корутин

withContext() — метод для выполнения действия в Dispatchers.IO. Возвращает значение, которое вернется из onboardingRepository.getOnboardingData()