Стратегия обработки ошибок в корутинах
Вопрос
Как ты организуешь обработку ошибок в корутинах в приложении: от репозитория до UI?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Ожидаемые ошибки ловлю близко к источнику и превращаю в результат
Корневые scope с SupervisorJob и CoroutineExceptionHandler для логирования
Независимые параллельные задачи в supervisorScope, зависимые в coroutineScope
CancellationException всегда пробрасываю
В UI ошибка как часть UiState
Не ставлю try вокруг launch
Что могут спросить следом
- Почему ViewModel не падает от одной упавшей корутины, но приложение падает?
- Как обработать ошибку в Flow?
- Что делать с ошибкой в async, у которого никто не вызвал await?
Разбор
Я разделяю ожидаемые и неожиданные ошибки. Ожидаемые, вроде сети, 404 или валидации, ловлю в репозитории или use case вокруг конкретного вызова и возвращаю как значение: sealed-результат или доменную ошибку. ViewModel превращает её в часть UiState, и UI просто рисует состояние ошибки. Неожиданные ошибки это баги, их не глушу, но для корневых scope задаю SupervisorJob и CoroutineExceptionHandler, который логирует в аналитику крэшей. Для параллельной работы выбираю scope по смыслу: если нужны все результаты, coroutineScope, пусть одна ошибка отменит остальные; если виджеты независимы, supervisorScope и try вокруг каждого await. Слежу за CancellationException: не ловлю Exception целиком и не использую голый runCatching, иначе отменённая корутина продолжит работу. И никогда не ставлю try вокруг launch: он вернётся раньше, чем случится ошибка.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Исключения в корутинах»
- Ошибка в async и try вокруг await
- CancellationException и родитель
- Где работает CoroutineExceptionHandler
- Ошибки в launch и async
- Распространение исключений
- CoroutineExceptionHandler в дочерней корутине
- launch(SupervisorJob()) внутри scope
- Путь необработанного исключения из дочернего launch