Home > Enterprise >  Remember not recompose when value change in jetpack compose
Remember not recompose when value change in jetpack compose

Time:11-25

I am increasing a value and I want to change color of text on that bases. When my value change my text color is not changing.

PairStateFul

@Composable
fun PairStateFul() {
    var selectedIndexOfAvailableItem by remember { mutableStateOf(-1) }
    val pairButtonColor = remember {
        if (selectedIndexOfAvailableItem != -1) {
            Color.Blue
        } else {
            Color.Yellow
        }
    }
    Column {
        PairStateLess(
           pairButtonColor,
            selectedIndexOfAvailableItem,
            onSelectedIndexOfAvailableItem = { selectedIndexOfAvailableItem  = it }
        )
    }

}

PairStateLess

@Composable
fun PairStateLess(pairButtonColor: Color,
    selectedIndexOfAvailableItem: Int,
    onSelectedIndexOfAvailableItem: (Int) -> Unit,
) {
        Text(
            "Hello World!",
            color = pairButtonColor
        )
    Button(onClick = {
        onSelectedIndexOfAvailableItem(selectedIndexOfAvailableItem)
    }) {
        Text(text = "item $selectedIndexOfAvailableItem")
    }
}

PairStateFulPreview

@Preview(showBackground = true)
@Composable
fun PairStateFulPreview() {
    PairStateFul()
}

I know my increase counter logic is wrong. I don't want to solve logic. My main problem is when selectedIndexOfAvailableItem change then my pairButtonColor will also change.

CodePudding user response:

In this case, you don't need a remember at all - Compose is already never going to change anything that pairButtonColor relies on unless selectedIndexOfAvailableItem changes, so can simply remove the remember and write:

val pairButtonColor =  if (selectedIndexOfAvailableItem != -1) {
    Color.Blue
} else {
    Color.Yellow
}

But to understand why your remember isn't working, it is important to understand what remember { } is doing. When you write

val pairButtonColor = remember {
  // ...
}

The code in the block is only run once and the value it returns is remembered (that's the whole point of remember).

This is why remember also has a version that take a single key or multiple keys:

Remember the value returned by calculation [your code block] if all values of keys are equal to the previous composition, otherwise produce and remember a new value by calling calculation.

Which would mean if you want your remember to rerun when selectedIndexOfAvailableItem changes, then it would need to be one of the keys you use:

val pairButtonColor = remember(selectedIndexOfAvailableItem) {
    if (selectedIndexOfAvailableItem != -1) {
        Color.Blue
    } else {
        Color.Yellow
    }
}

But as per the Best practices around using remember, usages of remember like this, where the source of the data is already a remembered value, are mostly around avoiding expensive calculations (i.e., if the block of code was very expensive to rerun, a remember on pairButtonColor might be helpful) or calculations that rely on remembered values that are changing rapidly (where remember derivedStateOf would help improve performance).

In your case, neither apply - an if check is something that doesn't require remember at all.

  • Related