TGViewer
Android under the hood Android under the hood @android_under_the_hood · 1.53K subscribers
Post #50 1.79K
Пару фактов о StateFlow и SharedFlow.

1) В отличии от простой реализации паттерна Observer, как это было в LiveData например, в StateFlow / SharedFlow механика основана на корутинах.

Всё начинается с подписки данных через collect, где запускается бесконечный цикл, который при отсутствии новых значений переводит корутину в SUSPEND состояние и что очень важно сохраняет ссылку на Continuation.

Думаю не секрет, что Continuation это обычный callback, который неявно передаётся в каждую suspend функцию и нужен для выхода из SUSPEND состояния.

При добавлении новых значений в StateFlow или SharedFlow извлекается сохранённый Continuation объект, у которого вызывается метод resume(), корутина выходит из SUSPEND состояния и подписчик получает новое значение или значения если это SharedFlow.

2) Состояния подписчиков, такие как ссылки на Continuation объекты, хранятся в массиве слотов AbstractSharedFlowSlot, по большей части это сделано для переиспользования общей логики, так как у StateFlow и SharedFlow общий родитель - AbstractSharedFlow.

3) Все возможные операции изменения состояния сделаны через атомарные конструкции (StateFlow) или synchronized блоки (SharedFlow), поэтому это потокобезопасные штуки.

4) StateFlow при изменении своего единственного значения сравнивает его с новым equals() методом, если значения равны, ничего не делает.

5) SharedFlow хранит значения в буфере, размер которого настраивается двумя параметрами: replay и extraBufferCapacity, первый отвечает за основную часть буфера, значения из этой части будут прилетать новым подписчикам, например если replay = 3, то при добавлении нового подписчика, в него придут 3 значения из буфера, второй параметр только добавляет дополнительное место для буферизации значений.

6) SharedFlow нельзя превратить в StateFlow если указать размер буфера нулевым, так как эта штука работает немного по другому, предположим у нас есть два подписчика и какой-нибудь источник в котором происходит генерация новых значений, все хорошо до тех пор пока один из подписчиков вдруг не окажется очень медленным и в случае нулевого размера буфера новое значение будет добавлено только когда все подписчики получат предыдущее, вызов SharedFlow.emit() в таком случае переходит в SUSPEND состояние.

Если буфер ненулевой то значения будут добавляться до тех пор пока он не заполнится.

7) Помимо перехода источников SharedFlow в SUSPEND состояние при переполнении буфера, есть ещё две интересные стратегии:

BufferOverflow.DROP_OLDEST - удаление из буфера самых старых значений

BufferOverflow.DROP_LATEST - пропуск новых значений, важно что здесь не происходит никаких операций с буфером

В обеих случаях SharedFlow.emit() успешно завершается и не переходит в SUSPEND состояние.

Пишите в комментах ваше мнение и всем хорошего кода!
  • 👍 21
  • 🔥 5
More from @android_under_the_hood
  1. Oct 4, 2026Всем привет, хочу поделиться проектом, который запустил 1 октября — ЗдесьЯ. Это цифровая с…
  2. Oct 2, 2026Kotlin lambdas, часть I. До версии Kotlin 2.0 лямбды компилировались в анонимные классы, р…
  3. Sep 27, 2026Делегат свойства в Kotlin. В Kotlin есть конструкция, которой нет в JVM: var name by NameD…
  4. Sep 23, 2026val vs var под капотом. На уровне Kotlin все просто: val x = 10 var y = 20 y = 30 // компи…
  5. Sep 20, 2026Возвращение Прошло уже полгода с последней записи на канале. За это время в моей жизни про…
  6. Feb 5, 2026Пару фактов о Go, часть II. 4) Вместо Kotlin Nullability указатели как в С/C++, то есть об…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →