Корутины
Приложениям часто нужно выполнять несколько задач одновременно: реагировать на ввод пользователя, загружать данные или обновлять экран. Для этого они используют конкурентное выполнение, при котором операции могут выполняться независимо и не блокировать друг друга.
Самый распространенный способ выполнять задачи конкурентно — использовать потоки: независимые пути выполнения, которыми управляет операционная система. Однако потоки относительно тяжелые, и создание большого количества потоков может привести к проблемам с производительностью.
Чтобы поддерживать эффективное конкурентное выполнение, Kotlin использует асинхронное программирование, построенное вокруг корутин. Корутины позволяют писать асинхронный код в естественном последовательном стиле с помощью приостанавливающих функций. Корутины — легковесная альтернатива потокам: они могут приостанавливаться, не блокируя системные ресурсы, экономно расходуют эти ресурсы и поэтому лучше подходят для мелкозернистой конкурентности.
Большинство возможностей корутин предоставляет библиотека kotlinx.coroutines.
Она включает инструменты для запуска корутин, управления конкурентным выполнением, работы с асинхронными потоками данных и
других задач.
Если вы только знакомитесь с корутинами в Kotlin, начните с руководства Основы корутин, прежде чем переходить к более сложным темам. В нем на простых примерах представлены ключевые понятия: приостанавливающие функции, билдеры корутин и структурированная конкурентность.
Посмотрите приложение KotlinConf как пример проекта, в котором корутины используются на практике.
Концепции корутин
Библиотека kotlinx.coroutines предоставляет основные строительные блоки для конкурентного выполнения задач, структурирования
выполнения корутин и управления разделяемым состоянием.
Приостанавливающие функции и билдеры корутин
Корутины в Kotlin построены на приостанавливающих функциях: они позволяют коду приостанавливаться и возобновляться, не
блокируя поток. Ключевое слово suspend помечает функции, которые могут асинхронно выполнять длительные операции.
Чтобы запускать новые корутины, используйте билдеры корутин, например
.launch() и
.async(). Эти билдеры
являются функциями-расширениями для
CoroutineScope,
который определяет жизненный цикл корутины и предоставляет контекст корутины.
Подробнее об этих билдерах можно узнать в разделах Основы корутин и Составление функций приостановки.
Контекст и поведение корутин
Запуск корутины из CoroutineScope создает контекст, управляющий ее выполнением. Функции-билдеры, такие как .launch() и
.async(), автоматически создают набор элементов, которые определяют поведение корутины:
- Интерфейс
Jobотслеживает жизненный цикл корутины и обеспечивает структурированную конкурентность. CoroutineDispatcherуправляет тем, где выполняется корутина: например, в фоновом потоке или в главном потоке UI-приложения.CoroutineExceptionHandlerобрабатывает неперехваченные исключения.
Эти и другие возможные элементы образуют контекст корутины, который по умолчанию наследуется от родительской корутины. Такой контекст формирует иерархию, обеспечивающую структурированную конкурентность: связанные корутины можно отменять вместе или обрабатывать исключения как группу.
Асинхронный поток и разделяемое изменяемое состояние
Kotlin предоставляет несколько способов коммуникации между корутинами. Выберите один из следующих вариантов в зависимости от того, как нужно передавать значения между корутинами:
Flowсоздает значения только тогда, когда корутина активно их собирает.Channelпозволяет нескольким корутинам отправлять и получать значения, при этом каждое значение доставляется ровно одной корутине.SharedFlowнепрерывно передает каждое значение всем активным собирающим корутинам.
Когда нескольким корутинам нужно обращаться к одним и тем же данным или обновлять их, они разделяют изменяемое состояние.
Без координации это может привести к состояниям гонки, когда операции непредсказуемо мешают друг другу. Чтобы безопасно
управлять разделяемым изменяемым состоянием, оберните общие данные в
StateFlow.
После этого можно обновлять их из одной корутины и собирать последнее значение из других.
Подробнее см. в разделах Асинхронный поток, Каналы и в руководстве Корутины и каналы.
Что дальше
- Изучите основы корутин, приостанавливающих функций и билдеров в руководстве Основы корутин.
- Разберитесь, как комбинировать приостанавливающие функции и строить конвейеры корутин, в разделе Составление функций приостановки.
- Узнайте, как отлаживать корутины с помощью встроенных инструментов IntelliJ IDEA.
- Для отладки, связанной с Flow, см. руководство Отладка Kotlin Flow с помощью IntelliJ IDEA.
- Прочитайте руководство по UI-программированию с корутинами, чтобы узнать о разработке UI на основе корутин.
- Ознакомьтесь с лучшими практиками использования корутин в Android.
- Посмотрите справочник API
kotlinx.coroutines.