Kotlin · 4 / 6

Flow, StateFlow и доставка событий

Replay, conflation, атомарность и отмена устаревшего поиска

Начните с требования к доставке

Построитель flow { } запускает блок для каждого коллектора. Сам интерфейс Flow не обещает холодность: StateFlow и SharedFlow тоже реализуют его. Для текущего состояния подходит StateFlow; для рассылки с заданной политикой replay — SharedFlow. StateFlow, SharedFlow.

Состояние не является журналом

StateFlow хранит текущее значение, подавляет равные обновления через equals, а медленный подписчик может пропустить промежуточные значения. Не меняйте список внутри текущего значения: создавайте новый снимок. StateFlow.

data class Screen(val selected: Set<Long> = emptySet())
val state = MutableStateFlow(Screen())
fun select(id: Long) {
    state.update { old -> old.copy(selected = old.selected + id) }
}

Нужны импорты MutableStateFlow и update из kotlinx.coroutines.flow. Лямбда update может выполниться повторно при конкуренции: сеть, логирование оплаты и выдача уникальных ID внутри неё недопустимы. update.

Подписчиков нет

У SharedFlow при отсутствии подписчиков остаются только replay-значения. extraBufferCapacity помогает отстающим активным подписчикам. У MutableSharedFlow() вызов tryEmit без подписчиков возвращает true, хотя значение потеряно. Для обязательного результата операции нужен явный протокол состояния и подтверждения, а иногда долговременное хранение. SharedFlow.

Поиск и отмена

debounce().flatMapLatest() отменяет прежнюю работу после того, как debounce выпустит новый запрос. Если отмена нужна сразу при вводе, задержку помещают внутрь latest-блока; результат дополнительно связывают с запросом. Это выбор требований, а не универсально лучший оператор. transformLatest.

Основа отбора: draft/coroutines.md, draft/compose_base.md, draft/lifeconding.md.

К вопросам →