Что такое корутины?
Корутины (coroutines) в Kotlin — это легковесные потоки, которые позволяют выполнять асинхронный и неблокирующий код в простом синтаксисе, похожем на синхронный. Они разработаны для эффективной работы с задачами, которые могут приостанавливаться и возобновляться без блокировки потоков.
Корутины — это одна из ключевых фич Kotlin и основа современного Android-разработки.
🔍 Зачем нужны корутины
Традиционный подход к асинхронному программированию (через Thread, AsyncTask, Callback, ExecutorService) имеет много недостатков:
-
сложность в управлении потоками,
-
callback hell,
-
утечки памяти,
-
плохая читаемость кода.
Корутины позволяют:
-
упростить асинхронный код;
-
не блокировать основной поток;
-
обрабатывать ошибки через try-catch;
-
управлять жизненным циклом через Job, Scope и Dispatcher.
🔹 Основные понятия
1. suspend функции
Это функции, которые могут быть приостановлены и возобновлены корутиной.
suspend fun fetchData(): String {
delay(1000) // не блокирует поток
return "result"
}
delay() — приостанавливает выполнение корутины, но не блокирует поток (в отличие от Thread.sleep()).
2. Запуск корутины: launch и async
GlobalScope.launch {
// фоновая задача
}
GlobalScope.async {
// фоновая задача с возвращаемым значением
}
-
launch — не возвращает результат, используется для «огневых» задач.
-
async — возвращает Deferred<T>, из которого можно получить результат через .await().
3. CoroutineScope
Это область действия, внутри которой живут корутины. Она управляет временем жизни и отменой.
val scope = CoroutineScope(Dispatchers.IO)
scope.launch {
// работает в пуле фоновых потоков
}
4. Dispatchers
Определяют, на каком потоке или пуле потоков выполняется корутина.
-
Dispatchers.Main — главный UI-поток.
-
Dispatchers.IO — для операций ввода-вывода (файлы, сети, БД).
-
Dispatchers.Default — для тяжёлых вычислений.
-
Dispatchers.Unconfined — запускается в текущем потоке, но может переключиться.
5. Job и отмена
Каждая корутина создаёт Job, которым можно управлять:
val job = scope.launch {
...
}
job.cancel() // отменяет выполнение
🔁 Пример корутины с launch
fun main() = runBlocking {
launch {
delay(1000)
println("Hello from coroutine!")
}
println("Main thread continues")
}
Вывод:
Main thread continues
Hello from coroutine!
→ runBlocking запускает корутину в блокирующем режиме, чтобы пример работал в main().
⚠️ Отличие от потоков
Параметр | Корутины | Потоки (Thread) |
---|---|---|
Легковесность | ✅ Да | ❌ Нет (тяжёлые) |
--- | --- | --- |
Кол-во в JVM | Миллионы | Тысячи |
--- | --- | --- |
Переключение | Быстрое, без контекста | Медленное, с контекстом |
--- | --- | --- |
Поддержка отмены | ✅ Да (через Job) | ❌ Нет по умолчанию |
--- | --- | --- |
API | Высокоуровневое | Низкоуровневое |
--- | --- | --- |
Применение в Android
-
Загрузка данных с сервера (через Retrofit + coroutines).
-
Работа с базами данных (Room поддерживает suspend-функции).
-
Асинхронные операции в ViewModel (через viewModelScope).
-
Использование Flow для реактивного стриминга данных.
📦 Библиотеки и интеграции
-
kotlinx.coroutines — официальная библиотека от JetBrains.
-
Поддержка в Android Jetpack: ViewModel, LiveData, Room, WorkManager.
-
Поддержка в Retrofit, ktor, SQLDelight и др.
🧠 Итого
Корутины — это эффективный инструмент для асинхронного программирования в Kotlin. Они позволяют писать понятный, читабельный и не блокирующий код, использовать suspend функции, работать с потоками через Dispatchers, и при этом избегать громоздкой синхронизации и колбэков. Они легковесны, отменяемы и легко масштабируются — именно поэтому они стали стандартом в Android-разработке.