'Jetpack compose remember
I was converting my simple paint app to compose and I came across a problem that I was able to fix, this question is for help in trying to understand why it behaved the way it did earlier, I tried searching for information on it but it compose is still a bit new and no much info online.
So, here is my original code snippet. By running this code, the lastSelected variable was always resetting back to 0 anytime I tried using it in the ColorPalette lambda, and when I checked the Tool lambda, the value was set correctly but it seems that during recomposition, the original value was retained.
@Composable
fun Toolbar(modifier: Modifier = Modifier, color: (Color) -> Unit, tool: (Int) -> Unit) {
// holds the currently selected tool index
var selected by rememberSaveable { mutableStateOf(0) }
var showColorPalette by rememberSaveable { mutableStateOf(false) }
var lastSelected = remember { 0 }
Column(
modifier = modifier.fillMaxWidth(0.8f),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Top,
) {
Row(
modifier = bar.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround,
) {
Tools.mapIndexed { index, tool ->
Tool(
name = tool.first, image = tool.second, selected = selected == index) {
selected = index
showColorPalette = (tool.second == R.drawable.ic_color_palette).also {
if (!it) {
lastSelected = index
tool(tool.second)
}
}
}
}
}
Spacer(modifier = Modifier
.height(8.dp)
.fillMaxWidth())
ColorPalette(isVisible = showColorPalette) { color ->
// revert the selected item back to the tool that was selected before
selected = lastSelected
// hide the color palette once a color is clicked
showColorPalette = false
// update the color used for drawing
color(color)
}
}
}
And here is my updated code snippet,
@Composable
fun Toolbar(modifier: Modifier = Modifier, color: (Color) -> Unit, tool: (Int) -> Unit) {
// holds the currently selected tool index
var selected by rememberSaveable { mutableStateOf(0) }
var showColorPalette by rememberSaveable { mutableStateOf(false) }
var lastSelected = remember { 0 }
fun updateColor(color: Color) {
// revert the selected item back to the tool that was selected before
selected = lastSelected
// hide the color palette once a color is clicked
showColorPalette = false
// update the color used for drawing
color(color)
}
fun updateTool(tool: Pair<String, Int>, index: Int) {
selected = index
showColorPalette = (tool.second == R.drawable.ic_color_palette).also {
if (!it) {
lastSelected = index
tool(tool.second)
}
}
}
Column(
modifier = modifier.fillMaxWidth(0.8f),
horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.Top,
) {
Row(
modifier = bar.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround,
) {
Tools.mapIndexed { index, tool ->
Tool(
name = tool.first, image = tool.second,
selected = selected == index, onClick = { (::updateTool)(tool, index) })
}
}
Spacer(modifier = Modifier
.height(8.dp)
.fillMaxWidth())
ColorPalette(isVisible = showColorPalette, onClick = ::updateColor)
}
}
After a long time of frustration because I could not understand why it was happening, I had a similar type of code in my DrawingCanvas file and the variable was remembered during recomposition, the only difference between them was that the place I was accessing and updating the variable in the DrawingCanvas file was an inner function, so I applied the same in this my code snippet and it seemed to work.
The variable's value is now remembered during recomposition.
I want to understand why this happens
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|