Можно ли запускать Coroutine через launch с задержкой или по триггеру
Что проверяют
Умеете ли вы управлять моментом старта корутины, не выходя за рамки structured concurrency. Интервьюеру важно, чтобы вы не предлагали опрос флага в цикле. Следом часто спрашивают про debounce в поиске или про судьбу отложенной задачи при повороте экрана.
Как отвечать
Можно, и способов несколько:
- задержка внутри корутины:
launch { delay(500); doWork() }.delayприостанавливает корутину, не блокируя поток, и отменяется вместе со скоупом; - ленивый старт:
val job = scope.launch(start = CoroutineStart.LAZY) { ... }, затемjob.start()илиjob.join()в нужный момент. Незапущенный ленивый потомок держит родительский скоуп: тот не завершится, пока корутину не запустят или не отменят; - ожидание события: корутина стартует сразу и приостанавливается до сигнала.
CompletableDeferredдля одного события,Channelдля очереди,stateFlow.first { it }для ожидания нужного состояния; - реакция на поток событий:
MutableSharedFlowилиStateFlow, а поверх нихcollect,debounce,filter.
Типичный Android-пример, поиск с задержкой: searchJob?.cancel(); searchJob = viewModelScope.launch { delay(300); repository.search(query) }. Каждый новый символ отменяет предыдущий запуск. То же самое декларативно делает queryFlow.debounce(300).collectLatest { ... }.
Скоуп выбирайте по времени жизни: viewModelScope переживает поворот экрана, lifecycleScope отменяется вместе с экраном, а сбор потоков в UI оборачивают в repeatOnLifecycle(Lifecycle.State.STARTED). Если задача должна выполниться через час или после закрытия приложения, корутина не подходит, она умрёт вместе с процессом. Для этого есть WorkManager с setInitialDelay.
Где спотыкаются
Ждут триггер циклом while (!flag) delay(500). Это лишние пробуждения и до полусекунды задержки на реакцию, а обычная var без @Volatile ещё и может не увидеть изменение из другого потока.
Запускают в GlobalScope. Корутина живёт дольше экрана, держит ссылки на него и не отменяется, когда пользователь ушёл.
Считают delay точным таймером. Это минимальная пауза: потом корутина ждёт свободный поток, и на загруженном Dispatchers.Main задержка выйдет больше.