Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Jetpack Compose detect change in variable for recomposition

I am doing a Google Codelab and have the following code (drawable changes when button is pressed):

@Composable
fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
    var result by remember { mutableStateOf(1) }
    val imageResource = when (result) {
        1 -> R.drawable.dice_1
        2 -> R.drawable.dice_2
        3 -> R.drawable.dice_3
        4 -> R.drawable.dice_4
        5 -> R.drawable.dice_5
        else -> R.drawable.dice_6
    }

    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(painter = painterResource(imageResource), contentDescription = result.toString())

        Button(onClick = { result = (1..6).random() }) {
            Text(text = stringResource(R.string.roll_text))
        }
    }
}

How does Compose know that result has changed when it triggers recomposition? Does it detect that through Image's painter parameter? Or maybe through remember or mutableStateOf()?

like image 1000
Vamoos Avatar asked Oct 16 '25 16:10

Vamoos


1 Answers

The answer is in the documentation:

mutableStateOf creates an observable MutableState<T>, which is an observable type integrated with the compose runtime. Any changes to this value schedules recomposition of any composable functions that read the value.

In your example when you click the button the result changes. imageResource reads this value and it triggers recomposition in nearest scope. Since the Column is an inline function (it means that Column doesn't have an own recompose scopes) the content of the Column is recomposed.

You can check it visually using this function:

fun randomColor() = Color(
    Random.nextInt(256),
    Random.nextInt(256),
    Random.nextInt(256),
    alpha = 255
)

Apply the same function to the background color of the Button and the Column:

    Column(
        modifier = Modifier.background(getRandomColor()),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Image(
            modifier = Modifier.background(getRandomColor()),
            painter = painterResource(R.drawable.ic_xxx), contentDescription = result.toString())

        Button(onClick = { result = (1..6).random() },
                colors= ButtonDefaults.buttonColors(containerColor = getRandomColor()),) {
            Text(text = "Button")
        }
    }

enter image description here

Note that in this example the Image uses a static resource and not the imageResource.

like image 86
Gabriele Mariotti Avatar answered Oct 18 '25 06:10

Gabriele Mariotti



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!