Suppose we have the following code. It displays a button, and when the user clicks on it, the button disappears.
@Composable
fun ButtonThatDisappearsOnClick() {
var showButton by remember { mutableStateOf(true) }
if (showButton) {
Button(onClick = {
check(showButton) { "onClick shouldn't be called for a hidden button" } // !!!
showButton = false
}) {
Text("My button")
}
}
}
I suspect that the check
call above may fail if the user clicks the button twice really quickly:
shouldShowButton
is set to false
. Since the value in a mutable state was updated, a recomposition is scheduled.onClick
function will fire the second time, and the check
call will fail.I have not been able to reproduce this in practice, so I am wondering if such a behavior is indeed possible.
This question is answer what you ask for. Op changes values consecutively but if state value changes before recomposition is completed it's a possibility that previous recomposition is discarded and new one is scheduled.
MutableState ignores first value if set two values in a row
SideEffect
function can be used for operations that should be invoked only when a successful recomposition happens
Recomposition starts whenever Compose thinks that the parameters of a composable might have changed. Recomposition is optimistic, which means Compose expects to finish recomposition before the parameters change again. If a parameter does change before recomposition finishes, Compose might cancel the recomposition and restart it with the new parameter.
When recomposition is canceled, Compose discards the UI tree from the recomposition. If you have any side-effects that depend on the UI being displayed, the side-effect will be applied even if composition is canceled. This can lead to inconsistent app state.
Ensure that all composable functions and lambdas are idempotent and side-effect free to handle optimistic recomposition.