In Jetpack Compose, most examples look something like this:
ScreenLevelContainer {
TopBar { ... }
ContentA { ... }
ContentB { ... }
// etc.
}
Contents of any given composable may be comprised of other deeply nested composables.
They talk about "state hoisting" such that application state should be stored at the high levels in the UI, or outside the UI entirely.
There seems to be a maintenance problem here though. Any state that TopBar
, its children, or the other content relies on needs to be passed through ScreenLevelContainer
, even though ScreenLevelContainer
has no explicit interest in the inner workings of TopBar
.
Moreover, if any of these children ever need to update the state that they take, one needs to go update any parents that include them, possibly in lots of places in a sufficiently complex application.
Pre-Compose, I would have used dependency inversion (and probably dependency injection) to solve this:
val topBar = TopBar(/* TopBar specific arguments */)
val contentA = ContentA(/* ContentA specific arguments */)
val contentB = ContentB(/* ContentB specific arguments */)
ScreenLevelContainer(topBar, contentA, contentB)
In the above code, any changes to TopBar
or the other content can happen independently of ScreenLevelContainer
. This becomes especially valuable when nested UI becomes complex. (Imagine TopBar
having an interactive shopping cart in it.)
What is the correct approach here?