In my app I have a top level Theme wrapper functio...
# compose
z
In my app I have a top level Theme wrapper function that just sets up the material 3 theme. It takes in a color for a custom dynamic theme and the variant (light/dark). For the longest time I couldn't figure out why everything was constantly recomposing. I just figured out the issue was with the color parameter So I changed from
fun Theme(color: Color, theme: Theme, useDynamicTheme: Boolean, content: @Composable () -> Unit)
to
fun Theme(color: ColorProducer, theme: Theme, useDynamicTheme: Boolean, content: @Composable () -> Unit)
What I don't get is why ColorProducer lambda fixes it. Color is immutable, so it shouldn't trigger recomposition, right? Is there something else I'm not understanding?
s
It shouldn't trigger recomposition unless it actually did change. Then it should. You say it happens when the color changes, no?
z
Yes, anytime the color changed it triggered, even if the color isnt being used when the dynamic theme is disabled. Heres the full function
Copy code
@Composable
fun Theme(color: ColorProducer, theme: Theme, useDynamicTheme: Boolean, content: @Composable () -> Unit) {
    if (useDynamicTheme) {
        DynamicMaterialTheme(
            seedColor = color(),
            useDarkTheme = theme == Theme.DARK || theme == Theme.SYSTEM && isSystemInDarkTheme(),
            style = PaletteStyle.Fidelity,
            content = content
        )
    } else {
        MaterialTheme(
            colorScheme = if (theme == Theme.DARK || theme == Theme.SYSTEM && isSystemInDarkTheme()) {
                darkColorScheme()
            } else {
                lightColorScheme()
            }
        ) {
            content()
        }
    }
}
s
Yeah that still makes sense. In the case of
ColorProducer
the
ColorProducer
itself does not change, so there is no reason for this composable to recompose. In the case of color, the color itself changes, so this composable needs to recompose to make sure that it does not show any stale data. I would assume that if you changed it to
Copy code
fun Theme(getColor: () -> Color, theme: Theme, useDynamicTheme: Boolean, content: @Composable () -> Unit) {
it would also manage to not recompose, since it'd be the same lambda across compositions and nobody would be asking for the color from inside of it