How to use rememberUpdatedState
最終更新日:2024-07-10
You may want to execute with arguments of Composable after performing time-consuming processing on LaunchedEffect
or DisposableEffect
.
@Composable
internal fun MyComposable(
done: () -> Unit,
) {
LaunchedEffect(Unit) {
// wait 3 seconds
delay(3000)
// call done given at Composable argument.
done()
}
Text("...")
}
We don't want to restart the coroutine every time done()
changes, so we specify Unit
as the argument to LaunchedEffect()
.
However, if re-compose is happened, done()
may change. In such cases, you can use rememberUpdatedState
.
@Composable
internal fun MyComposable(
done: () -> Unit,
) {
val currentDone by rememberUpdatedState(done)
LaunchedEffect(Unit) {
// wait 3 seconds
delay(3000)
// call the value of rememberUpdatedState
currentDone()
}
Text("...")
}
Now, after doing some time-consuming processing, done()
that is replaced with the latest will be called.
Example
As It's hard to understand by Official document,let's look at a specific example.
@Composable
fun MainScreen() {
var counter by remember { mutableStateOf(0) }
// for result
var goodDone by remember { mutableStateOf(-1) }
var badDone by remember { mutableStateOf(-1) }
// capture current value
val v = counter
Column(modifier = Modifier.padding(paddingValues)) {
Bad(
count = counter,
doneValue = badDone,
) {
badDone = v
}
Good(
count = counter,
doneValue = goodDone,
) {
goodDone = v
}
// button to increment counter
Button(onClick = {
++counter
}) {
Text("Add")
}
}
}
For Bad
, we will call the argument done()
directly.
@Composable
fun Bad(
count: Int,
doneValue: Int,
done: () -> Unit,
) {
LaunchedEffect(Unit) {
delay(3000)
// call directly
done()
}
Text("Count=${count} done=${doneValue}")
}
For Good
, we will call the value of rememberUpdatedState
.
@Composable
fun Good(
count: Int,
doneValue: Int,
done: () -> Unit,
) {
val currentDone by rememberUpdatedState(done)
LaunchedEffect(Unit) {
delay(3000)
// call the value of rememberUpdatedState
currentDone()
}
Text("Count=${count} done=${doneValue}")
}
Run it and press the button repeatedly within 3 seconds.
For Bad
, done()
is from the first composition so the doneValue
became 0. For Good
, done()
is from the last time composition so the doneValue
became 9.