-
Notifications
You must be signed in to change notification settings - Fork 95
Description
In a weird combination of StateFlow
, backgroundScope
, UnconfinedTestDispatcher
, collectAsState()
and the Immediate
recomposition mode the Compose runtime stops recomposing and Flows produced by Molecule stop sending events.
This test passes:
@Test
fun `something breaks`() = runTest {
val _strings = MutableStateFlow("one")
val strings: Flow<String> = _strings
val molecule = (backgroundScope + UnconfinedTestDispatcher(testScheduler)).launchMolecule(RecompositionMode.Immediate) {
val string by strings.collectAsState("one")
string
}
molecule.test {
assertThat(awaitItem()).isEqualTo("one")
_strings.value = "two"
assertThat(awaitItem()).isEqualTo("two")
_strings.value = "three"
assertThat(awaitItem()).isEqualTo("three")
}
}
If I change the initial value to something else such as collectAsState("abc")
, then only "one" from the StateFlow is emitted but no other value anymore even though the StateFlow value changes. The composable function only recomposes when the initial value of the StateFlow
and the collectAsState
function are equal. This seems to be the bug.
Changing the flow to a MutableSharedFlow
fixes the issue, because there’s no default value. Removing the UnconfinedTestDispatcher
also fixes the issue. In this case it emits the initial value from collectAsState
first, then the default value from the StateFlow
and then all other changes. Using the same initial values also resolves the bug (the problem here is that StateFlow
is an implementation detail of the underlying API, this example is simplified). It only breaks when the initial values are different.