Mofe Ejegi
08/28/2025, 5:02 PMrememberSaveable
inputs. I assumed it's meant to work just like remember
keys or like LaunchedEffect
keys where any change in any of the keys would trigger a re-calculation or re-run of the init block.
But for some reason, it does't always run - it gives inconsistent results across different devices, and sometimes even on the same device.
Take a look at this code below, why does the print statement in the LaunchedEffect
and the remember
block work, but not the rememberSaveable
?
val density = LocalDensity.current
val d = density.density
val f = density.fontScale
println("Density: $d, Font Scale: $f")
LaunchedEffect(d, f) {
println("Screen density changed, resetting content height")
}
val testRememberHeight by remember(d, f) {
println("Recalculating test height")
mutableFloatStateOf(0f)
}
val contentHeightDp by rememberSaveable(d, f) {
println("Recalculating content height")
mutableFloatStateOf(0f)
}
Am I doing something wrong? Perhaps the way I'm changing the density (using the Android Studio Emulator quick tools) isn't the correct way?
Though I clearly see the logs printed indicating the Density and Scale changing.Mofe Ejegi
08/28/2025, 5:56 PMrememberSaveable
block. In that case, it always prints, so perhaps this has something to do with how the density is updated.Zach Klippenstein (he/him) [MOD]
08/28/2025, 7:03 PMrememberSaveable
. Both d
and f
are primitive values, so shouldn't be anything weird here. This sounds like a bug to meMofe Ejegi
08/28/2025, 9:47 PMZach Klippenstein (he/him) [MOD]
08/28/2025, 10:17 PMDensity
instances at a higher level?Mofe Ejegi
08/29/2025, 2:58 PMrememberSaveable
is designed to execute it's calculation block during recomposition, but when config changes occur, it seems to favour restoring the last saved state, without factoring the inputs passed before the config change. I don't know if this is by design or a bug.
So assuming I had something like:
@Composable
fun TestCompose() {
val isDark = isSystemInDarkTheme()
println("Is Dark: $isDark")
LaunchedEffect(isDark) {
println("Theme changed: $isDark")
}
val testRememberHeight by remember(isDark) {
println("Recalculating test height")
mutableFloatStateOf(0f)
}
val contentHeightDp by rememberSaveable(isDark) {
println("Recalculating content height")
mutableFloatStateOf(0f)
}
}
Switching themes will re-initialize the composable, and this causes LaunchedEffect
and remember
to print again, independent of the fact that the isDark
boolean got toggled. LaunchedEffect(Unit)
and remember()
with no keys would do the same.
However, rememberSaveable
does nothing since its state has already been saved with a key and its value is simply restored, even though the input (which is tied to the config) was changed.Mofe Ejegi
08/29/2025, 3:02 PMZach Klippenstein (he/him) [MOD]
08/29/2025, 5:37 PM