[Программирование] kotlinx.coroutines 1.4.0: представляем StateFlow и SharedFlow (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В преддверии старта курса "Kotlin Backend Developer" приглашаем всех желающих записаться на открытый урок по теме "Kotlin multiplatform: front/back на одном языке".
А сейчас предлагаем к прочтению традиционный перевод статьи.
Сегодня мы с радостью объявляем о выходе версии 1.4.0 библиотеки Kotlin Coroutines . Основными новшествами этого релиза стали StateFlow и SharedFlow, которые теперь являются стабильными API-интерфейсами. StateFlow и SharedFlow предназначены для использования в тех случаях, когда требуется управление состоянием в контексте асинхронного выполнения с применением Kotlin Coroutines.
API-интерфейс Flow в Kotlin предназначен для асинхронной обработки потока данных, который выполняется последовательно. По сути, Flow — это последовательность. В Kotlin с помощью Flow можно выполнять такие же операции, как с помощью Sequences: преобразовывать, фильтровать, сопоставлять и т. д. Основное различие между Sequences и Flow в Kotlin заключается в том, что Flow позволяет приостанавливать выполнение.Во Flow приостановку можно выполнить в любом месте: в функции сборки или в любом из операторов, предоставляемых API-интерфейсом Flow. Приостановка во Flow работает как контроль backpressure, при этом вам не нужно ничего делать — всю работу выполняет компилятор.
val flow: Flow<Int> = flow {
delay(100)
for(i in 1..10) {
emit(i)
}
}.map {
delay(100)
it * it
}
Интерфейс Flow так же прост в использовании, как и Sequences. Однако Flow несет в себе все преимущества реактивного программирования, в котором не требуется управлять backpressure.Flow является удобным API-интерфейсом, однако он не обеспечивает возможность управлять состоянием, которая требуется в некоторых случаях. Например, у процесса может быть несколько промежуточных и одно конечное состояние. Примером такого процесса является загрузка файла: процесс загрузки длится некоторое время и мы можем определить такие промежуточные состояния процесса, как «Запущен» и «Выполняется», и конечные состояния «Успешно» и «Сбой». В этом случае нам интересны только результаты: успешно была выполнена загрузка или нет.При реализации описанного выше сценария с помощью API-интерфейса Flow нам нужно публиковать изменения состояния для наблюдателей, которые могут совершать те или иные действия исходя из этих изменений. Ранее мы всегда рекомендовали использовать для этого ConflatedBroadcastChannel. Однако ConflatedBroadcastChannel является слишком сложным для этой задачи. Кроме того, имеются некоторые логические нестыковки, которые возникают при использовании каналов для управления состоянием. Например, канал может быть закрыт или отменен. Это не очень хорошо сочетается с управлением состоянием, поскольку состояние-то нельзя отменить!Мы решили отказаться от ConflatedBroadcastChannel и вместо этого внедрить пару новых API-интерфейсов — StateFlow и SharedFlow!StateFlowStateFlow имеет две разновидности: StateFlow и MutableStateFlow:
public interface StateFlow<out T> : SharedFlow<T> {
public val value: T
}
public interface MutableStateFlow<out T>: StateFlow<T>, MutableSharedFlow<T> {
public override var value: T
public fun compareAndSet(expect: T, update: T): Boolean
}
Состояние представлено значением. Любое изменение значения будет отражено во всех коллекторах потока путем выдачи значения с изменениями состояния.Давайте посмотрим, как можно реализовать описанный ранее пример с загрузкой файла с помощью нового API-интерфейса.
class DownloadingModel {
private val _state.value = MutableStateFlow<DownloadStatus>(DownloadStatus.NOT_REQUESTED)
val state: StateFlow<DownloadStatus> get() = _state
suspend fun download() {
_state.value = DownloadStatus.INITIALIZED
initializeConnection()
processAvailableContent {
partialData: ByteArray,
downloadedBytes: Long,
totalBytes: Long
->
storePartialData(partialData)
_state = DownloadProgress(downloadedBytes.toDouble() / totalBytes)
}
_state.value = DownloadStatus.SUCCESS
}
}
В этом примере клиентам предоставляется неизменяемая версия state, а управление изменяемым состоянием (state) выполняется внутри. В функции загрузки мы сначала обновляем внутреннее значение состояния: state.value = DownloadStatus.INITIALIZED. Затем мы можем обновлять внутреннее состояние, задавая промежуточные числа, которые указывают ход выполнения загрузки. Наконец, state получит конечное значение, указывающее состояние загрузки.Как видите, никаких API для работы с каналами здесь не используется. Мы не запускаем никаких дополнительных корутин, и нет нужды изучать какие-либо новые концепции. Только простой императивный код, в котором для описания реализации используется переменная, а клиентам предоставляется state как Flow.SharedFlowЧто, если вместо управления состоянием нам потребуется управлять рядом обновлений состояния, то есть потоком событий? Для таких случаев у нас есть новый API-интерфейс под названием SharedFlow. Этот API-интерфейс подходит для обработки ряда выдаваемых значений, например для вычисления скользящего среднего из потока данных.
public interface SharedFlow<out T> : Flow<T> {
public val replayCache: List<T>
}
Общий поток — это просто поток, где есть кэш повтора, который можно использовать в качестве атомарного моментального снимка. Каждый новый подписчик сначала получает значения из кэша повтора, а затем получает новые выданные значения.Вместе с SharedFlow мы также предоставляем MutableSharedFlow.
interface MutableSharedFlow<T> : SharedFlow<T>, FlowCollector<T> {
suspend fun emit(value: T)
fun tryEmit(value: T): Boolean
val subscriptionCount: StateFlow<Int>
fun resetReplayCache()
}
С помощью MutableSharedFlow можно выдавать значения из приостанавливающего и неприостанавливающего контекста. Как можно заключить из имени, кэш повтора MutableSharedFlow можно сбрасывать. Кроме того, он предоставляет количество своих коллекторов как поток.Реализовать собственный MutableSharedFlow может быть довольно сложно. Поэтому мы предоставляем несколько удобных методов для работы с SharedFlow.
public fun <T> MutableSharedFlow(
replay: Int,
extraBufferCapacity: Int = 0,
onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
): MutableSharedFlow<T>
Чтобы инициализировать экземпляр MutableSharedFlow с помощью приведенной выше функции, можно указать количество значений, которые повторяются для новых подписчиков, емкость буфера, а также действия, которые следует выполнять в случае заполнения буфера. Например, если буфер заполнится, можно приостановить поток.Если у вас уже есть экземпляр потока и вы хотите обеспечить возможность предоставления к нему общего доступа, можно воспользоваться новым оператором Flow.shareIn.
public fun <T> Flow<T>.shareIn(
scope: CoroutineScope,
replay: Int,
started: SharingStarted = SharingStarted.Eagerly
)
РезюмеНовые API-интерфейсы StateFlow и SharedFlow обеспечивают более элегантный способ работы с состоянием в программах на Kotlin с корутинами. Они намного проще и понятнее, чем использование широковещательных каналов для публикации изменений состояния из контекста потока.Попробуйте новые API, испытайте их на прочность и отправьте нам свой отзыв!Подробные сведения о нововведениях в Kotlin Coroutines можно узнать, посмотрев выступление Всеволода Толстопятова на конференции Kotlin 1.4 Online Event.
Узнать подробнее о курсе "Kotlin Backend Developer".
Записаться на открытый урок "Kotlin multiplatform: front/back на одном языке".
===========
Источник:
habr.com
===========
===========
Автор оригинала: Anton Arhipov
===========Похожие новости:
- [Kotlin, Конференции] Серия вебинаров по серверной разработке на Kotlin
- [Программирование, Разработка под Android] Подменяем Runtime permissions в Android
- [Программирование, Go, Микросервисы] Создаем высокопроизводительные микросервисы с помощью gRPC, Ballerina и Go (перевод)
- [Open source, Программирование, C++] Не хочется ждать в очереди? Напишем свой диспетчер для SObjectizer с приоритетной доставкой
- [Проектирование и рефакторинг, API, Профессиональная литература] Книга: проектирование API
- [Системное программирование, Интерфейсы, Разработка под Linux, Программирование микроконтроллеров] Configuring FT4232H using the ftdi_eeprom
- [Программирование, .NET, Управление персоналом, Карьера в IT-индустрии, Интервью] Заметки про интервью на разработчика
- [Серверная оптимизация, API, DevOps] Haproxy — программирование и конфигурирование средствами Lua
- [Системное программирование, Интерфейсы, Разработка под Linux, Программирование микроконтроллеров] Конфигурируем FT4232H c помощью утилиты ftdi_eeprom
- [Программирование, Алгоритмы, Go] Algorithms in Go: Sliding Window Pattern
Теги для поиска: #_programmirovanie (Программирование), #_kotlin, #_backend, #_api, #_stateflow, #_blog_kompanii_otus._onlajnobrazovanie (
Блог компании OTUS. Онлайн-образование
), #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:38
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В преддверии старта курса "Kotlin Backend Developer" приглашаем всех желающих записаться на открытый урок по теме "Kotlin multiplatform: front/back на одном языке".
А сейчас предлагаем к прочтению традиционный перевод статьи. API-интерфейс Flow в Kotlin предназначен для асинхронной обработки потока данных, который выполняется последовательно. По сути, Flow — это последовательность. В Kotlin с помощью Flow можно выполнять такие же операции, как с помощью Sequences: преобразовывать, фильтровать, сопоставлять и т. д. Основное различие между Sequences и Flow в Kotlin заключается в том, что Flow позволяет приостанавливать выполнение.Во Flow приостановку можно выполнить в любом месте: в функции сборки или в любом из операторов, предоставляемых API-интерфейсом Flow. Приостановка во Flow работает как контроль backpressure, при этом вам не нужно ничего делать — всю работу выполняет компилятор. val flow: Flow<Int> = flow {
delay(100) for(i in 1..10) { emit(i) } }.map { delay(100) it * it } public interface StateFlow<out T> : SharedFlow<T> {
public val value: T } public interface MutableStateFlow<out T>: StateFlow<T>, MutableSharedFlow<T> { public override var value: T public fun compareAndSet(expect: T, update: T): Boolean } class DownloadingModel {
private val _state.value = MutableStateFlow<DownloadStatus>(DownloadStatus.NOT_REQUESTED) val state: StateFlow<DownloadStatus> get() = _state suspend fun download() { _state.value = DownloadStatus.INITIALIZED initializeConnection() processAvailableContent { partialData: ByteArray, downloadedBytes: Long, totalBytes: Long -> storePartialData(partialData) _state = DownloadProgress(downloadedBytes.toDouble() / totalBytes) } _state.value = DownloadStatus.SUCCESS } } public interface SharedFlow<out T> : Flow<T> {
public val replayCache: List<T> } interface MutableSharedFlow<T> : SharedFlow<T>, FlowCollector<T> {
suspend fun emit(value: T) fun tryEmit(value: T): Boolean val subscriptionCount: StateFlow<Int> fun resetReplayCache() } public fun <T> MutableSharedFlow(
replay: Int, extraBufferCapacity: Int = 0, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND ): MutableSharedFlow<T> public fun <T> Flow<T>.shareIn(
scope: CoroutineScope, replay: Int, started: SharingStarted = SharingStarted.Eagerly ) Узнать подробнее о курсе "Kotlin Backend Developer".
Записаться на открытый урок "Kotlin multiplatform: front/back на одном языке". =========== Источник: habr.com =========== =========== Автор оригинала: Anton Arhipov ===========Похожие новости:
Блог компании OTUS. Онлайн-образование ), #_programmirovanie ( Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:38
Часовой пояс: UTC + 5