Search code examples
androidkotlinandroid-jetpack-compose

android dev recompose when clicked on a button question


I am doing this excersize to build a dice app.

It works but here is what I am confused about: Based on my understanding every time I click on the button Roll it triggers a recompose.

When I click on the Roll button it randomly picks a number between 1 and 6. And then this number is remembered and then the whole screen is recomposed?

And that's when the imageResource is selected based on the result that is remembered from the previous recompose?

And then that is rendered via Image?

Am I understanding this right?


@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())
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = { result = (1..6).random()}) {
            Text(stringResource(R.string.roll))
            
        }

    }

}

Solution

  • Your overall understanding is correct. However, it might be useful to understand the concept at little but more in depth:

    • You click the Button, and a new random value is assigned to the result variable.
    • You declared the result variable using mutableStateOf(). This allows Jetpack Compose to detect when you assign a new value to the variable and to trigger the recomposition.
    • Composable functions that depend on the result variable will be recomposed with the new result value.
    • Composable functions that do not depend on the result variable will
      • be skipped from recomposition when their input parameters are stable
      • be recomposed when their input parameters are not stable
    • All variables that are not persisted using remember() will be reset / recomputed.
    • All normal Kotlin functions will be re-executed.
    • You declared the result variable using remember(). This ensures that the value of the result variable is not reset during this recomposition.

    These concepts can be demonstrated in the following example:

    @Composable
    fun MyComposable() {
        var result by remember { mutableStateOf(1) }
    
        Column(
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(
                onClick = {
                    Log.d("MyComposable", "Dices are rolling...")
                    result = (1..6).random()
                }
            ) {
                Text("ROLL")
            }
            Spacer(modifier = Modifier.weight(1f))
    
            // Composable depends on result variable
            // will recompose when result variable is updated
            Text(text = "result: $result")
    
            // Composable does not depend on result variable, but has unstable parameter
            // will recompose whenever parent Composable recomposes 
            Text(text = "randomResult: ${(7..12).random()}")
    
            // Composable does not depend on the result variable and has stable parameter
            // will not recompose when parent Composable recomposes
            Text(text = "some constant text")
    
            // normal Kotlin function
            // will be re-executed whenever parent Composable recomposes
            Log.d("MyComposable", "Dices are done")
    
        }
    }
    

    The Logcat output after each onClick is as follows:

    2024-04-29 10:38:29.122 10618-10618 MyComposable   D  Dices are rolling...
    2024-04-29 10:38:29.137 10618-10618 MyComposable   D  Dices are done