Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Kotlin: корутина

Что такое Structured Concurrency и как его нарушить?

Этот вопрос проверяет понимание структурированной конкурентности в Kotlin и типичных ошибок, которые её нарушают.

Короткий ответ

Structured Concurrency – это подход, при котором корутины запускаются в определённой области (CoroutineScope), и их жизненный цикл связан с этой областью. Если область отменяется, отменяются и все её корутины.

Нарушить Structured Concurrency можно:

  1. Запуская корутины в GlobalScope (они живут независимо от контекста).

  2. Создавая корутины без явного Job или SupervisorJob.

  3. Используя launch или async вне CoroutineScope.

Длинный ответ

1. Как работает Structured Concurrency?

  • Каждая корутина запускается внутри CoroutineScope (например, viewModelScope, lifecycleScope).

  • Если область (scope) отменяется, автоматически отменяются все её корутины.

  • Это предотвращает утечки памяти и неконтролируемые фоновые операции.

Пример правильного использования:

viewModelScope.launch {  
    	val data = fetchData()  // Если ViewModel очищается, корутина отменяется  
    	updateUi(data)  
}  

2. Как нарушить Structured Concurrency?

Запуск в GlobalScope

GlobalScope.launch {  // ❌ Корутина живёт всё время работы приложения  
    	doSomething()     // Если экран закрыт, она продолжит работать  
}  

Проблема: Корутина не привязана к жизненному циклу компонента (Activity, ViewModel).

Неявный Job без отмены

fun startBackgroundTask() {  
    	val job = launch {  // ❌ Где scope? Если он не передан, корутина может висеть в памяти  
        	heavyWork()  
    	}  
}  

Проблема: Нет контроля над отменой, возможна утечка.

Потеря ссылки на Job

fun startTask() {  
    	val job = viewModelScope.launch {  
        	delay(1000)  
        	updateUi()  // Может сработать после очистки ViewModel  
    	}  
    	// job не отслеживается и не отменяется явно  
}  

Проблема: Если экран закрыт до завершения delay, updateUi() вызовет краш.


3. Как исправить?

  • Всегда использовать viewModelScope, lifecycleScope или явный CoroutineScope с Job.

  • Отменять корутины при очистке ресурсов (onCleared, onDestroy).

  • Использовать coroutineScope или supervisorScope для вложенных корутин.

Пример безопасного кода:

class MyViewModel : ViewModel() {  
    	private val customScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)  

    	fun fetchData() {  
        	customScope.launch {  
            		try {  
                		val result = apiCall()  
                		withContext(Dispatchers.Main) { updateUi(result) }  
            		} catch (e: Exception) { handleError(e) }  
        	}  
    	}  

    	override fun onCleared() {  
        	customScope.cancel()  // ✅ Все корутины отменяются при очистке ViewModel  
    	}  
}  

Вывод:
Structured Concurrency делает управление корутинами предсказуемым. Нарушая её, мы рискуем получить утечки памяти и неожиданное поведение. Всегда связывайте корутины с областью видимости!

  • Аватар

    Android Guru

    Anton Gulyaev

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    5

  • Сложность:

    8

Навыки

  • Kotlin

    Kotlin

Ключевые слова

#корутина

Подпишись на Android Developer в телеграм

  • Аватар

    Android Guru

    Anton Gulyaev

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.