I have a Composable function like this, when `Text...
# compose
f
I have a Composable function like this, when
Text1
recomposes, the
Image
also recomposes, but
Text2
doesn't. How can I prevent the
Image
from recomposing when
Text1
changes?
Copy code
var num by remember { mutableStateOf(0) }
var text by remember { mutableStateOf("text") }
LaunchedEffect(Unit) {
    while (isActive) {
        delay(1000)
        num++
    }
}
FirstScreen(
    number = num,
    text = text,
    onImageClick = {}
)

@Composable
fun FirstScreen(
    number: Int,
    text: String,
    onImageClick: () -> Unit
) {
    Column {
        Text("$number")
        Image(
            painter = painterResource(resource = Res.drawable.compose_multiplatform),
            contentDescription = null,
            modifier = Modifier.clickable(onClick = onImageClick)
        )
        Text(text)
    }
}
Besides moving the
Image
to a separate Composable, are there other ways to optimize this? What’s considered the best practice?
z
Why do you want to do that?
f
To skip unnecessary recomposition since the
Image
itself hasn’t changed.
z
It’s a waste of time to chase down every single unnecessary recomposition just for the sake of it. Is this causing measurable performance issues for you?
f
I agree that chasing every recomposition is impractical.Of course, this example is simplified. In production, UI hierarchies are often more complex.Knowing why
Image
recomposes helps fix real performance issues when they appear.
Recomposition because of
Modifier.clickable
, clickable with InteractionSource / Indication parameters can optimize this. https://issuetracker.google.com/issues/241154852#comment10
m
It makes little sense here, but here extracting a function and passing getter would help.
Copy code
var num by remember { mutableStateOf(0) }
var text by remember { mutableStateOf("text") }
LaunchedEffect(Unit) {
    while (isActive) {
        delay(1000)
        num++
    }
}
FirstScreen(
    number = { num },
    text = text,
    onImageClick = {}
)

@Composable
fun FirstScreen(
    number: () -> Int,
    text: String,
    onImageClick: () -> Unit
) {
    Column {
        NumberText(number)
        Image(
            painter = painterResource(resource = Res.drawable.compose_multiplatform),
            contentDescription = null,
            modifier = Modifier.clickable(onClick = onImageClick)
        )
        Text(text)
    }
}
f
The simplest way is to modify the clickable method, which may need to enable strong skipping mode.
Copy code
@Composable
fun FirstScreen(
    number: Int,
    text: String,
    onImageClick: () -> Unit
) {
    Column {
        Text("$number")
        Image(
            painter = painterResource(resource = Res.drawable.compose_multiplatform),
            contentDescription = null,
            modifier = Modifier.clickable(
                interactionSource = remember { MutableInteractionSource() },
                indication = null,
                onClick = onImageClick
            )
        )
        Text(text)
    }
}