Job и SupervisorJob
Вопрос
Объясни разницу между Job и SupervisorJob, coroutineScope и supervisorScope, с примерами из Android.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Job: ошибка ребёнка отменяет родителя и братьев
SupervisorJob: дети падают независимо
coroutineScope и supervisorScope это то же самое для вложенного блока
viewModelScope и lifecycleScope на SupervisorJob
Supervisor не обрабатывает ошибку, нужен try или handler
launch(SupervisorJob()) это ошибка
Что могут спросить следом
- Что будет с async в supervisorScope, если не вызвать await?
- Почему CoroutineExceptionHandler работает в детях supervisorScope?
Разбор
В обычном Job дети связаны одной судьбой: ошибка любого отменяет родителя, а он отменяет остальных. Это правильно, когда задачи части одного целого, например нужны и профиль, и настройки, чтобы показать экран. SupervisorJob разрывает распространение вверх: упавший ребёнок завершается один, остальные продолжают. Так устроены viewModelScope и lifecycleScope, чтобы падение одного запроса не отменяло всё на экране. Для вложенного блока те же два поведения дают coroutineScope и supervisorScope: оба ждут всех детей, но первый отменяет всех при ошибке, второй нет. Важно, что супервизор не обрабатывает исключение: в прямых детях supervisor оно уходит в CoroutineExceptionHandler, а без него роняет приложение. Частая ошибка: launch(SupervisorJob()) внутри scope. Это не делает детей независимыми и ещё отрывает корутину от родителя. Правильно supervisorScope { }.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Исключения в корутинах»
- Ошибка в async и try вокруг await
- CancellationException и родитель
- Где работает CoroutineExceptionHandler
- Ошибки в launch и async
- Распространение исключений
- CoroutineExceptionHandler в дочерней корутине
- launch(SupervisorJob()) внутри scope
- Путь необработанного исключения из дочернего launch