Mbt925
10/23/2023, 7:18 AM@Composable
fun Test() {
var isShown by remember { mutableStateOf(false) }
val opacity by animateFloatAsState(targetValue = if (isShown) 0f else 0.5f, label = "")
Column(Modifier.statusBarsPadding()) {
Button(
onClick = { isShown = !isShown }) { Text(text = "Toggle text") }
Text(text = "Hello world", modifier = Modifier.graphicsLayer { alpha = opacity })
}
}
The above composable works fine. The recomposition of Hello world text is skipped as expected. However, if I replace graphicsLayer { alpha = opacity }
with Modifier.animateAlpha { opacity }
using the following function, it recomposes every time the button is clicked:
@Stable
fun Modifier.animateAlpha(alpha: () -> Float) = this.graphicsLayer {
this.alpha = alpha()
}
Any insight into the issue is appreciated.Albert Chang
10/23/2023, 8:48 AMThe above composable works fine. It doesn't recompose Hello world text every time, but only once.I doubt if that's true. I would expect the function to be recomposed every time the button is clicked because without a recomposition, the
targetValue
of animateFloatAsState
can't be updated.Mbt925
10/23/2023, 9:04 AMAlbert Chang
10/23/2023, 9:09 AMwithout a recomposition, theAnd by recomposition I mean all the phases including composition phase.oftargetValue
can't be updated.animateFloatAsState
Mbt925
10/23/2023, 9:11 AMAlbert Chang
10/23/2023, 9:20 AMCaveat: Inline composable functions
section in this post for the reason.Mbt925
10/23/2023, 9:28 AMAlbert Chang
10/23/2023, 9:49 AM{ alpha = opacity }
is memoized (i.e. it will always be the same instance across compositions) and so the modifier will be considered the same, in which case the Text
call can be skipped. But in the second case, while { opacity }
is memoized, the lambda in the Modifier.animateAlpha
function isn't, as memoization only happens in composable functions. Therefore the lambda passed to Modifier.graphicsLayer
won't be the same instance, and so the modifier won't be considered the same.Mbt925
10/23/2023, 10:38 AMAlbert Chang
10/23/2023, 10:43 AMval lambda = { opacity }
val modifier = remember(lambda) {
Modifier.animateAlpha(lambda)
}
Btw, avoid premature optimization.Mbt925
10/23/2023, 11:00 AMModifier.alpha
extension, if it doesn't do what it's supposed to do (only affecting the drawing phase)? How are we supposed to delegate complex logic to extension functions on Modifiers then?Albert Chang
10/23/2023, 11:18 AMModifier.Node
. That's always the best approach.Francesc
10/23/2023, 3:36 PMWhy is there aextension, if it doesn't do what it's supposed to doModifier.alpha
Modifier.alpha
is simpler to use than graphicsLayer { alpha = x }
if you have a static alpha, not an animating one