In a Jetpack Compose application, I have two composables similar to here:
@Composable
fun Main() {
println("Composed Main")
val context = LocalContext.current
var text by remember { mutableStateOf("") }
fun update(num: Number) {
text = num.toString()
Toast.makeText(context, "Toast", Toast.LENGTH_SHORT).show()
}
Column {
Text(text)
Keypad { update(it) }
}
}
@Composable
fun Keypad(onClick: (Number) -> Unit) {
println("Composed Keypad")
Column {
for (i in 1..10) {
Button(onClick = {onClick(i)}) {
Text(i.toString())
}
}
}
}
Clicking each button causes the two composables to recompose and produces this output:
I/System.out: Composed Main
I/System.out: Composed Keypad
Recomposing the Keypad
composable is unneeded and makes the app freeze (for several seconds in a bigger project).
Removing usages of context in the event handles (in here, commenting out the Toast
) solves the problem and does not recompose the Keypad
and produces this output:
I/System.out: Composed Main
Is there any other way I could use context in an event without causing unneeded recompositions?
CodePudding user response:
That's actually weird why Toast affects the recomposition of KeyPad
when its showing, but considering Toast is kind of a side-effect not an actual part of the composable (I'm expecting a correction here) I thought of putting it in an Effect to prevent Keypad
from recomposing, and it did.
Here, SideEffect
will execute every post-recomposition.
SideEffect {
if (text.isNotEmpty()) {
Toast.makeText(context, "Toast", Toast.LENGTH_SHORT).show()
}
}
or you can utilize LaunchedEffect
using the text
as its key, so on succeeding re-compositions, when the text
changes, different from its previous value (invalidates), the LaunchedEffect
will re-execute and show the toast again
LaunchedEffect(key1 = "text") {
if (text.isNotEmpty()) {
Toast.makeText(context, "Toast", Toast.LENGTH_SHORT).show()
}
}
Replacing your print with Log statements, this is the output when clicking any buttons, either of the effect being used
E/Composable: Composed Main // first launch of screen
E/Composable: Composed Keypad // first launch of screen
// succeeding clicks
E/Composable: Composed Main
E/Composable: Composed Main
E/Composable: Composed Main
E/Composable: Composed Main