Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda function used as input argument causes recomposition

Consider snippet below

fun doSomething(){
}

@Composable
fun A() {
    Column() {
        val counter = remember { mutableStateOf(0) }
        B {
            doSomething()
        }
        Button(onClick = { counter.value += 1 }) {
            Text("Click me 2")
        }
        Text(text = "count: ${counter.value}")
    }
}

@Composable
fun B(onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("click me")
    }
}

Now when pressing "click me 2" button the B compose function will get recomposed although nothing inside it is got changed.

Clarification: doSomething is for demonstration purposes. If you insist on having a practical example you can consider below usage of B:

B{
    coroutinScope.launch{
        bottomSheetState.collapse()
        doSomething()
    }
}

My questions:

  1. Why this lamda function causes recomposition
  2. Best ways to fix it

My understanding of this problem

From compose compiler report I can see B is an skippable function and the input onClick is stable. At first I though its because lambda function is recreated on every recomposition of A and it is different to previous one. And this difference cause recomposition of B. But it's not true because if I use something else inside the lambda function, like changing a state, it won't cause recomposition.

My solutions

  1. use delegates if possible. Like viewmode::doSomething or ::doSomething. Unfortunately its not always possible.
  2. Use lambda function inside remember:
val action = remember{
    {
        doSomething()
    }
}
B(action)

It seems ugly =) 3. Combinations of above.

like image 373
Ali Golmirzaei Avatar asked Mar 31 '26 22:03

Ali Golmirzaei


1 Answers

Sometimes function reference viewModel::doShomething also triggers recomposition. In that case and solution that works is to capture lambda inside remember

val onClick = remember {
    { index: Int ->
        viewModel.toggleSelection(index)
    }
}

You can see the answer here

Why does a composable recompose while seemingly being stateless (the only passed parameter is a function, not a state)

or stability edit section when you use on clicks inside LazyColumn or other Lazy lists.

Jetpack Compose lazy column all items recomposes when a single item update

like image 56
Thracian Avatar answered Apr 02 '26 14:04

Thracian



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!