We're using a Crossfade inside a top-level Scaffold to fade between "screens". However, different screens need different TopBar icons and onClickListeners, which we currently set-up inside the screens using onActive(). This would translate to DisposableEffect without a key, which is declared as sign of a bug.
Since crossfade renders stuff in weird order, how are we supposed to ensure the set-up code for the topbar is only launched "onActive"? Or in general: aren't there things that are supposed to run once when components become visible? Setting focus is another example.
I guess the whole pattern we use may be wrong (setting up the top-bar from within subcomponents), so I'd be happy to hear about other solutions, too.
02/01/2021, 4:57 PM
Yes, setting up the top-bar from within subcomponents is wrong. It violates several principles (composables are functional transforms of data to UI, data is passed top down, etc).
The decision of what to show should be hoisted up above the top bar. Often this decision is hoisted all the way up into the activity and the data lives in the app or activity instead of living in the composable tree. But either way, widgets should never have side-effects on their parents.
Especially when you're new to Compose, your best bet is to try to model all your data as immutable data and all your composables as stateless composables (https://developer.android.com/jetpack/compose/state#stateless-composables) and that will train your brain to start "thinking in Compose".
02/01/2021, 7:31 PM
Thanks. For the most cases, i think i found good compose-style solutions, but I'm still having a hard time figuring this one out.
I mean sure, i can set the topbar up somewhere else, but I'd like to have the behaviour of topbar buttons defined inside the "screens". For example, we have a filter button in the TopBar that should filter a list view on one screen. On another screen, another button may be shown for a different purpose.
I can't propagate the click events down the tree, because it's not a state. I can't really perform the action in the MainActivity (or top-level composable), because it doesn't have knowledge of the viewmodels of the sub screens (i shouldn't keep all ViewModels at the top, or should i?).
I could use separate Scaffolds, but then again, I need a permanent BottomBar, because it has some fancy transition animation between screens.