Какие знаешь типы корутин?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы корутин в Kotlin
В Kotlin корутины можно классифицировать по нескольким ключевым критериям: по способу создания, области видимости, потоку выполнения и особенностям поведения. Вот основные типы:
1. По способу создания и запуска
launch-корутины
Это корутины, которые запускаются без явного возврата результата (возвращают Job). Используются для fire-and-forget задач.
scope.launch {
// Выполнение фоновой задачи
delay(1000)
println("Завершено")
}
async-корутины
Корутины, возвращающие Deferred<T> (аналог Future/Promise), позволяющий получить результат позже через await().
val deferredResult = scope.async {
delay(500)
return@async 42
}
// В другом месте
val result = deferredResult.await()
produce-корутины (экспериментальные в kotlinx.coroutines)
Создают каналы (Channel) для потоковой передачи данных.
val channel = scope.produce {
for (i in 1..5) {
send(i * i)
}
close()
}
2. По области видимости (CoroutineScope)
Глобальные корутины (GlobalScope)
Запускаются в глобальной области видимости и живут всё время работы приложения. Не рекомендуются в Android из-за рисков утечек памяти.
GlobalScope.launch {
// Работает пока не завершится или не будет отменена
}
Локальные скоупы (CoroutineScope)
Связаны с жизненным циклом компонентов (Activity, ViewModel, Fragment).
viewModelScope(в Android Architecture Components)lifecycleScope(в Android Lifecycle)- Пользовательские скоупы с
SupervisorJobи диспетчерами
class MyViewModel : ViewModel() {
fun fetchData() {
viewModelScope.launch {
// Автоматически отменяется при очистке ViewModel
}
}
}
3. По контексту выполнения (CoroutineDispatcher)
Основной (UI) поток (Dispatchers.Main)
Для операций с UI в Android, Swing, JavaFX.
scope.launch(Dispatchers.Main) {
updateUI()
}
Фоновые диспетчеры
Dispatchers.IO– для I/O операций (сеть, файлы, БД)Dispatchers.Default– для CPU-интенсивных задач (сортировка, вычисления)Dispatchers.Unconfined– не привязан к конкретному потоку (осторожно!)
scope.launch(Dispatchers.IO) {
val data = fetchFromNetwork() // Блокирующий вызов
withContext(Dispatchers.Main) {
showData(data) // Возвращаемся в UI поток
}
}
4. По особенностям поведения
Супервизорные корутины (SupervisorJob/supervisorScope)
Когда сбой в одной дочерней корутине не отменяет другие.
supervisorScope {
launch { task1() } // Если упадёт,
launch { task2() } // это продолжит работу
}
Структурированная параллельность
Иерархия корутин, где родитель управляет дочерними:
parentScope.launch {
// Дочерние корутины
launch { child1() }
launch { child2() }
} // Все дочерние завершатся/отменятся при завершении родителя
Отменяемые vs неотменяемые
- Отменяемые – стандартные корутины, поддерживающие cooperative cancellation
- Неотменяемые – с использованием
NonCancellableконтекста
withContext(NonCancellable) {
// Критическая операция, которая должна завершиться
closeResources() // Даже при отмене корутины
}
5. По взаимодействию с потоками
Потокобезопасные корутины
Используют Mutex, Semaphore, атомарные переменные или withContext для безопасного доступа к общим ресурсам.
Актор-корутины (экспериментальные)
Реализуют паттерн Actor для обработки сообщений с гарантией последовательного выполнения.
val actor = scope.actor<Message> {
for (msg in channel) {
process(msg)
}
}
Практическое значение
Различие типов корутин критически важно для:
- Управления жизненным циклом в Android
- Предотвращения утечек памяти
- Оптимизации производительности (правильный выбор диспетчера)
- Обработки ошибок (супервизор vs обычный job)
- Тестирования (использование
TestDispatcher)
Например, в Android приложении типичная структура выглядит так:
class Repository {
suspend fun loadData(): Data = withContext(Dispatchers.IO) {
// Сетевой запрос
}
}
class MyViewModel : ViewModel() {
fun load() {
viewModelScope.launch {
try {
val data = repository.loadData()
_state.value = Success(data)
} catch (e: Exception) {
_state.value = Error(e)
}
}
}
}
Здесь сочетаются: viewModelScope (скоуп с жизненным циклом), launch-корутина для фоновой задачи, Dispatchers.IO для сетевого вызова, и структурированная отмена при очистке ViewModel.
Понимание этих типов позволяет строить отзывчивые, стабильные и эффективные асинхронные приложения, полностью используя преимущества корутин Kotlin.