'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