Как будут вести себя StateFlow и SharedFlow при изменении конфигурации

Ответ

StateFlow и SharedFlow ведут себя по-разному при изменении конфигурации:

StateFlow
Сохраняет свое состояние (последнее emitted значение) и продолжает работу после изменения конфигурации. Подписчики получат последнее значение при повторной подписке.

val stateFlow = MutableStateFlow(0) // сохранит значение при повороте

SharedFlow
Не хранит состояние (если не используется replay). При изменении конфигурации:

  • Теряет все не доставленные события
  • Новые подписчики не получат старые значения (если replay = 0)
  • Можно использовать replay для кэширования N последних значений
val sharedFlow = MutableSharedFlow<Int>(replay = 1) // сохранит 1 последнее значение

Для обоих случаев поток продолжает работать в фоне, но подписки View будут пересозданы.

Ответ 18+ 🔞

А, ну это классика, блядь! Смотри, тут история про то, как эти два потока ведут себя, когда ты экран крутишь, как еблан. Представь, что ты в приложении сидишь, а тут — бац! — поворот экрана. Всё пересоздаётся, а эти потоки-то живут своей жизнью. И вот в чём, сука, разница, ёпта.

StateFlow — это как упрямый батя, который всё помнит. Он, блядь, сохраняет своё последнее значение (это его «состояние», state, отсюда и имя, хитрая жопа). После того как экран перевернулся и твоя View заново подписывается, этот поток сразу плюёт ей в лицо последним известным значением. «На, получай, неблагодарный!» — как будто говорит. Он не теряет ни хуя.

val stateFlow = MutableStateFlow(0) // сохранит значение 0 (или любое другое) при повороте

Новый подписчик прилетит — и сразу получит цифру. Удобно, чё. Доверия к нему — овердохуища.

SharedFlow — это уже другой чувак, более гибкий, но и более похуистичный. По умолчанию он — не хранит состояние. Представь радиостанцию: если ты вышел из комнаты (поворот экрана), то то, что диджей наговорил, пока тебя не было, ты нихуя не услышишь. События теряются нахуй.

  • Все события, которые летели, но не дошли до подписчика, который умер (твоя View), — накрылись медным тазом.
  • Новый подписчик (пересозданная View) приходит — а ему тишина в ответ, если replay = 0. Ни хуя себе, да?

Но он не совсем уж пидарас шерстяной, ему можно настроить replay. Скажешь ему: «Запоминай, блядь, одно последнее значение», и он станет почти как StateFlow.

val sharedFlow = MutableSharedFlow<Int>(replay = 1) // сохранит 1 последнее значение, как StateFlow-малыш

Самое главное, что оба этих товарища продолжают хуярить в фоне, пока твой ViewModel жив. Поток не прерывается. Вся хуйня в том, что подписки из View (типа collect в lifecycleScope) — те отвалятся и пересоздадутся. А источник данных-то тёпленький, живой, значения как летели, так и летят.

Короче, выбор простой:

  • Нужно последнее состояние всегда под рукой — StateFlow, ебать мои старые костыли, идеально.
  • Нужна просто шина событий (типа «показать тост», «навигация»), где потеря прошлых сообщений не страшна — SharedFlow с replay = 0.
  • Хочешь, чтобы SharedFlow тоже что-то помнил — выкручивай ему replay. Всё, вопрос закрыт, иди нахуй.