Мягкое введение в корутины Kotlin для Android-разработчиков
· 3 мин чтения · 6 апреля 2025
Фото: Vlad Kutepov на Unsplash
Добро пожаловать... в мягкое введение в корутины Kotlin для Android-разработчиков.
Что такое корутины и зачем они нужны?
Корутины — это код, который может выполняться параллельно (ожидая чего-то другого). Пример параллелизма — нарезка овощей во время ожидания закипания воды в кастрюле.
Потоки могут делать то же самое, однако корутины работают внутри потоков. Корутины легковесны, поэтому их можно запускать гораздо больше, чем потоков. Мы используем их, чтобы сделать наш код быстрее и эффективнее.
Основы корутин:
coroutine scope (область видимости корутин): Сегмент кода, который существует до завершения всех корутин внутри него. Может включать обычные функции и suspend-функции.
Пример: runBlocking{ // код здесь }, coroutineScope{ // код здесь }
suspend functions (подвешиваемые функции): Как обычные функции, но могут быть остановлены или задержаны, особенно полезны для параллелизма. Suspend-функция должна находиться внутри области видимости корутин.
Пример: suspend fun myFunction(){ // код здесь }
launch: Создает и запускает корутины для параллельной работы (используется каждый раз, когда задача должна работать, пока другие ожидают). Launch можно вызывать только внутри области видимости корутин.
dispatchers (диспетчеры): Менеджеры потоков, когда нужно разместить корутины в определенных потоках. Разные потоки работают параллельно, но они тяжелее корутин, запущенных через launch. Если диспетчер не указан, используется Dispatchers.Default.
Пример: Dispatchers.IO, Dispatchers.Main
job: Завершенная корутина. Каждый блок launch может возвращать job. Это полезно, если у вас есть корутины, но неизвестно, когда они завершатся. Вызов .join() на переменной job заставит код ждать завершения корутины. Также можно отменить job с помощью .cancel(), чтобы завершить его досрочно.
Вот примеры кода из документации Kotlin для launch и job:
Источник
Важно отметить, что при отмене jobs они должны сотрудничать или периодически проверять сигналы остановки. В приведенном коде цикл while делает это каждый раз, проверяя булево значение isActive. isActive — это ключевое слово-переменная, которая отслеживает, активен ли job.
async — как launch, но вместо возврата job (который не возвращает конкретного значения), async может возвращать значение после завершения корутины, доступное через функцию await.
Источник
Как корутины работают с Android?
Android имеет специальные области видимости корутин, которые работают в течение жизненного цикла ViewModel или Activity/Fragment, называемые viewModelScope или lifecycleScope соответственно.
viewModelScope и lifecycleScope можно вызывать вместо runBlocking. Это хорошая практика и практически необходимость — не блокировать UI во время фоновых операций в Android-приложении, таких как сетевой запрос.
Для таких функций обычно оборачивают их в блок viewModelScope.launch и размещают на диспетчере, отличном от основного потока. (Для обычных областей используется Dispatchers.Default, для viewModelScope и lifecycleScope — Dispatchers.Main).
Вот пример в действии... сетевой API-запрос в классе ViewModel внутри функции. Это было для API базы данных фильмов, который возвращал JSON-строку, затем парсился и передавался в UI.
На этом мягкое введение заканчивается. :) Основные ресурсы включают документацию Kotlin, которую можно найти ниже для более продвинутых тем.