Mark
09/15/2025, 4:28 PMSharedFlow
(application level coroutine scope with replay = 1) in compose using collectAsStateWithLifecycle
(initialValue = null), I notice that on screen rotation the first value is null
, but shouldn’t it be sharedFlow.replayCache.firstOrNull()
? The reason I ask, is because scroll position is being lost on rotation, but when I use ``replayCache.firstOrNull()`` as the initialValue
everything works as expected.Caleb Cook
09/15/2025, 4:55 PMreturn produceState(initialValue, this, lifecycle, minActiveState, context) {
lifecycle.repeatOnLifecycle(minActiveState) {
if (context == EmptyCoroutineContext) {
this@collectAsStateWithLifecycle.collect { this@produceState.value = it }
} else withContext(context) {
this@collectAsStateWithLifecycle.collect { this@produceState.value = it }
}
}
}
which passes null into produce, setting its value to null before collecting from the shared flow. It would then get the cached value from the shared flow in the collect block, but by then you've collected the null value.
Notice the overload of collectAsStateWithLifecycle
that extends StateFlow
just calls .collectAsStateWithLifecycle(initialValue = this.value, ...)
which is pretty much the same thing you're doing when you are explicitly providing the initial value.Mark
09/15/2025, 5:08 PMcollectAsStateWithLifecycle
provides the passed in initialValue
first.Winson Chiu
09/15/2025, 5:18 PMSharedFlow
specific extension which checks the replay cache. 🤔Mark
09/15/2025, 5:45 PMSharedFlow
you still need to provide an initialValue to cover the case where the replayCache
is empty. And so in that case it’s more like the Flow extension fun than the StateFlow extension fun. Also, I guess a SharedFlow is often passed around as a Flow anyway.