Какие виды Job бывают в Kotlin Coroutines и в чем их отличия
Что проверяют
Понимаете ли вы, что Job это жизненный цикл корутины, и знаете ли разницу обычного и супервизорного варианта.
Как отвечать
Job это дескриптор запущенной корутины: он хранит состояние (новая, активная, завершается, завершена, отменена), позволяет отменить её и дождаться через join. Задачи образуют дерево: отмена родителя отменяет потомков, а родитель не завершится, пока живы дети.
Виды:
- обычный Job: ошибка в дочерней корутине отменяет родителя и всех её братьев. Это поведение по умолчанию и оно правильное там, где задачи part одного целого;
- SupervisorJob: ошибка потомка не трогает ни родителя, ни соседей. Нужен, когда задачи независимы: три параллельные загрузки на экране, где падение одной не должна гасить остальные;
- Deferred:
Jobс результатом, возвращается изasync, результат забирается черезawait.
Есть и парная разница в билдерах: coroutineScope отменяет всё при ошибке любой части, supervisorScope изолирует ошибки потомков.
Важная тонкость, которую и проверяют: SupervisorJob работает, только если он корень области. Передать его в launch бесполезно, потому что билдер создаёт свой дочерний Job, и изоляция не появится.
Отмена во всех случаях кооперативная: корутина обязана доходить до точек приостановки или сама проверять ensureActive().
Где спотыкаются
Передают SupervisorJob в launch и удивляются, что изоляции нет.
Ловят CancellationException общим catch и ломают отмену.
Считают, что Job можно перезапустить: отменённая задача мертва окончательно.
Не знают, что исключение из async всплывает только на await.