Ответ
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. Всё, вопрос закрыт, иди нахуй.