Consider we have the following structure in a toggling implementation scenario:
@Composable
fun RootComposable() {
var someAuxToggle by remember { mutableStateOf(false) }
if (someAuxToggle) {
FirstComposable { someAuxToggle = !someAuxToggle }
} else {
SecondComposable { someAuxToggle = !someAuxToggle }
}
}
@Composable
fun FirstComposable(auxCallback: () -> Unit) {
val myRandomNumber by remember { mutableStateOf(Random.nextInt(100)) }
Button(onClick = { auxCallback() }) {
Text(text = "I'm the FirstComposable.\nMy random is: $myRandomNumber")
}
}
@Composable
fun SecondComposable(auxCallback: () -> Unit) {
val myRandomNumber by remember { mutableStateOf(Random.nextInt(100)) }
Button(onClick = { auxCallback() }) {
Text(text = "I'm the SecondComposable.\nMy random is: $myRandomNumber")
}
}
Doing this, the toggling works, the composables are correclty called, however their own state changes, once I'm "recreating" then. This is also valid if those buttons was placed inside other top composables and these top composables be called.
Now, if we implement this in a little hacky way the state keeps alive (the random numbers are not regenerated):
@Composable
fun RootComposable() {
var someAuxToggle by remember { mutableStateOf(false) }
Box(
if (someAuxToggle)
Modifier.wrapContentSize()
else
Modifier.size(0.dp)
) {
FirstComposable { someAuxToggle = !someAuxToggle }
}
Box(
if (someAuxToggle)
Modifier.size(0.dp)
else
Modifier.wrapContentSize()
) {
SecondComposable { someAuxToggle = !someAuxToggle }
}
}
@Composable
fun FirstComposable(auxCallback: () -> Unit) {
val myRandomNumber by remember { mutableStateOf(Random.nextInt(100)) }
Button(onClick = { auxCallback() }) {
Text(text = "I'm the FirstComposable.\nMy random is: $myRandomNumber")
}
}
@Composable
fun SecondComposable(auxCallback: () -> Unit) {
val myRandomNumber by remember { mutableStateOf(Random.nextInt(100)) }
Button(onClick = { auxCallback() }) {
Text(text = "I'm the SecondComposable.\nMy random is: $myRandomNumber")
}
}
Note that in this implementation both buttons are being called inside root but the toggling was made by switching their "visibility", via setting their sizes.
Also note that the buttons composable are really the same component, but my idea is just demonstrate the state behaviour.
My question is about the best way to keep the state if we call a composable again, like in the first code; if there are a simple way to do it or if we really need to store those states in some top level fields or something like this.
Also, is the second approach too expensive in terms of performance? I think yes, because both composable are "turned on" all the time, then if we have composables that makes hard work (e.g., via side effects or even background tasks) then performance can be lowered.
Anyway, I hope we find a solution to that.