← Назад к вопросам

В чем разница между обработкой ошибки в корутине с помощью try/catch и CoroutineExceptionHandler?

2.8 Senior🔥 111 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между try/catch и CoroutineExceptionHandler в Kotlin

Это два фундаментально разных подхода к обработке ошибок в корутинах, каждый имеет свою область применения.

try/catch для обработки обычных исключений

try/catch — это стандартный механизм обработки исключений, который синхронно ловит ошибки в коде корутины. Это работает так же, как в обычном коде:

launchIO {
    try {
        val data = fetchDataFromNetwork() // может выбросить исключение
        updateUI(data)
    } catch (e: Exception) {
        showError(e.message)
    }
}

Это локальный способ обработки: вы явно указываете, какой код может выбросить ошибку, и как её обработать. Плюсы:

  • Явная обработка в том месте, где она нужна
  • Точный контроль над типами исключений
  • Полная типизация (обработка IOException отдельно от NetworkException)

CoroutineExceptionHandler для глобальной обработки

CoroutineExceptionHandler — это глобальный обработчик ошибок для корутины, который ловит необработанные исключения на уровне всей корутины. Это не касается исключений, которые были обработаны try/catch:

val exceptionHandler = CoroutineExceptionHandler { _, exception ->
    showGlobalError(exception.message)
    logError(exception)
}

viewModelScope.launch(exceptionHandler) {
    val data = fetchDataFromNetwork() // если исключение не обработано локально
    updateUI(data)
}

Ключевая разница

Параметрtry/catchCoroutineExceptionHandler
ОбластьЛокальная, в пределах блокаГлобальная для всей корутины
СрабатываниеНа месте выброса исключенияТолько если исключение не обработано локально
ИспользованиеОбработка конкретных ошибокСетка безопасности для критических ошибок
Множественные блокиМожно иметь несколько try/catch в одной корутинеОдин обработчик на корутину

Практический пример

val handler = CoroutineExceptionHandler { _, exception ->
    // Вызовется ТОЛЬКО если исключение не обработано локально
    Log.e("Global", "Необработанная ошибка: ${exception.message}")
    showCrashDialog()
}

viewModelScope.launch(handler) {
    try {
        // Эта ошибка будет обработана здесь
        val userData = fetchUser() // выброситься ParsingException
    } catch (e: ParsingException) {
        showUserMessage("Ошибка парсинга")
        // handler НЕ сработает, так как мы обработали ошибку
    }
    
    // Эта ошибка попадёт в handler
    val posts = fetchPosts() // выбросится NetworkException
}

Когда что использовать

try/catch — когда вы знаете, что может пойти не так, и готовы обработать это:

  • Парсинг JSON
  • Сетевые запросы в наивысшей точке иерархии бизнес-логики
  • Работа с файлами
  • Валидация пользовательского ввода

CoroutineExceptionHandler — для страховки от неожиданных ошибок:

  • Необработанные исключения в async блоках
  • Критические ошибки, которые должны упасть приложение или вывести пользователю сообщение
  • Логирование всех необработанных ошибок

Оптимальный подход — комбинировать оба: используйте try/catch для известных ошибок, а CoroutineExceptionHandler как финальную сеть безопасности.

В чем разница между обработкой ошибки в корутине с помощью try/catch и CoroutineExceptionHandler? | PrepBro