> В чем отличие launch от async в Kotlin Coroutines (Kotlin, Android)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: MTS, Rutube, IBS
Стек: Kotlin, Android
> Пример ответа
Короткий ответ
launch и async - оба способа запустить корутину, но с разным назначением. launch возвращает Job и предназначен для fire-and-forget задач, которые не возвращают результат. async возвращает Deferred (наследник Job), который позволяет получить результат через await(). Основной trade-off: async добавляет оверхед на создание Deferred, поэтому для задач без результата используйте launch.
Подробное объяснение
launch - это builder, который запускает корутину и немедленно возвращает управление. Возвращаемый Job позволяет отменять корутину, но не предоставляет доступа к результату её выполнения. Исключения внутри launch пробрасываются в родительский контекст сразу (если не перехвачены).
async - это builder, который возвращает Deferred<T> - promise-подобный объект. Результат вычисляется асинхронно, и вы можете получить его через await(). await() приостанавливает текущую корутину до завершения вычисления. Исключения внутри async не пробрасываются сразу - они хранятся в Deferred и выбрасываются при вызове await().
Ключевые различия:
- Возвращаемый тип:
JobvsDeferred<T> - Назначение: side-effect операции vs вычисление результата
- Обработка исключений: немедленная vs отложенная до
await() asyncбезawait()- это анти-паттерн, если только вы не используете structured concurrency с явной отменой
На практике
В Android-разработке launch используется для операций с UI: обновление View, запись в БД, отправка аналитики. async - для параллельного выполнения независимых вычислений, когда нужен результат: например, загрузка данных из нескольких источников с последующей агрегацией.
Типичный паттерн - async внутри coroutineScope для параллельного выполнения:
coroutineScope { val user = async { fetchUser() } val posts = async { fetchPosts() } show(user.await(), posts.await()) }
Здесь оба запроса выполняются параллельно, а await() последовательно собирает результаты.
Важно: async без await() создаёт утечку ресурсов, если корутина не отменяется. В Android это критично при работе с ViewModel - используйте viewModelScope и отменяйте через Job.
Пример кода
// launch - fire-and-forget fun loadData() { viewModelScope.launch { repository.saveData() // результат не нужен } } // async - нужен результат fun loadUserAndPosts() { viewModelScope.launch { val user = async { repository.getUser() } val posts = async { repository.getPosts() } // оба запроса выполняются параллельно val result = combine(user.await(), posts.await()) _uiState.value = result } } // Обработка исключений fun handleErrors() { viewModelScope.launch { try { val data = async { riskyOperation() }.await() } catch (e: Exception) { // исключение из async ловится здесь } } }
Как отвечать на собеседовании
Начните с чёткого разграничения: launch - для задач без результата, async - для задач с результатом. Затем добавьте про Deferred и await(). Упомяните structured concurrency и важность отмены корутин. Приведите пример из реальной практики - параллельная загрузка данных. Если спросят про исключения - объясните разницу в propagation. Завершите trade-off: async имеет смысл только когда вы действительно используете результат, иначе это лишний оверхед.
Что проверяет интервьюер
- Понимание базовых концепций coroutines:
Job,Deferred, structured concurrency - Умение выбирать правильный builder под задачу
- Знание особенностей обработки исключений
- Понимание lifecycle корутин и важности отмены
- Практический опыт: параллельное выполнение,
await(), работа сviewModelScope
Типичные ошибки
- Использование
asyncдля задач без результата - лишний оверхед и сложность - Забывание
await()- результат теряется, корутина выполняется впустую - Игнорирование исключений из
async- они не всплывают автоматически - Вызов
asyncвнеcoroutineScope- потеря structured concurrency - Путаница между
DeferredиJobпри отмене корутин - Использование
asyncдля последовательных операций - лучше простоlaunchс suspend-функциями
> Похожие задачи по mobile
Что такое тип Nothing в Kotlin и чем он отличается от Unit
Что такое reified в inline функциях Kotlin и зачем он нужен
Что такое CoroutineExceptionHandler
Какие диспетчеры бывают в Kotlin Coroutines
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью