Что такое CoroutineScope и CoroutineContext
Что проверяют
Понимаете ли вы структурированную конкурентность: кто владеет корутиной и когда она отменяется. Это главное отличие корутин от голых потоков.
Как отвечать
CoroutineContext это набор элементов, описывающих, как выполнять корутину: диспетчер (Dispatchers.Main, IO, Default), Job (жизненный цикл и отмена), имя для отладки, обработчик исключений. Элементы складываются оператором +.
CoroutineScope это просто держатель контекста, у которого есть Job. Он задаёт границу жизни: отмена области отменяет все запущенные в ней корутины, а сама область не завершится, пока не завершатся дочерние. В этом и состоит структурированная конкурентность, корутина не может «убежать» и пережить свой экран.
class ProfileViewModel : ViewModel() {
fun load() = viewModelScope.launch(Dispatchers.IO) { repository.fetch() }
}Готовые области в Android: viewModelScope (умирает вместе с ViewModel), lifecycleScope (вместе с активностью или фрагментом). Свою заводят там, где нужен собственный жизненный цикл, и обязательно отменяют.
Отдельно про исключения: в обычном Job падение дочерней корутины отменяет всю область, в SupervisorJob только саму упавшую. Для независимых задач нужен второй вариант.
Где спотыкаются
Используют GlobalScope: он не привязан ни к чему, корутина переживает экран и течёт вместе с ссылками на него.
Считают, что диспетчер и область это одно и то же.
Не знают про SupervisorJob и удивляются, что одна упавшая загрузка отменила остальные.
Ловят CancellationException общим catch и ломают отмену: её нужно пробрасывать.