3

Smart recomposition in Jetpack Compose works by so called donut-hole skipping, which leads to only those scopes being recomposed, that need to be (since something might have changed in it). This question is a perfect example on how different layout structuring, wrapping / scoping can prevent unnecessary recompositions.

Take this example:

@Composable
fun Parent(someString: String) {
    var someParameter by remember { mutableStateOf(true) }
    Column {
        Child1()
        Child2(someString)
        Child3(someParameter)
    }
}

If someParameter would change, not only Child3 would be recomposed, but also the Parent (which I think would also lead to Child2 recomposition because of someString) since Child3 is not in it is own "capsulated" scope.

To prevent this, I could theoretically put every Child in their own dedicated Scope (wrapping them in another non-inline-fun composable) like this:

@Composable
fun ScopedView(content: @Composable () -> Unit) {
    content()
}

@Composable
fun Parent(someString: String) {
    var someParameter by remember { mutableStateOf(true) }
    Column {
        ScopedView { Child1() } }
        ScopedView { Child2(someString) }
        ScopedView { Child3(someParameter) }
    }
}

This seems to solve all those "problems" with unnecessary recompositioning, but I've never seen this kind of approach anywhere during my research. Why? Are there any drawbacks or a better solutions to this?

z.g.y
  • 5,512
  • 4
  • 10
  • 36
Dominik Seemayr
  • 830
  • 2
  • 12
  • 30
  • 2
    There is no need for such tricks; generally recomposition is not a bad or heavy thing. If your views have no side effects (read more at [thinking in compose](https://developer.android.com/jetpack/compose/mental-model)), recomposition will not take a significant amount of time. For example, during animation, recomposition happens once per frame, and this is expected behavior, but it does not lead to performance problems if you do it right. Of course, it is better to have fewer recompositions, but if it made a significant difference in performance, `Column` would not be `inline`. – Phil Dukhov Feb 13 '22 at 10:58
  • @PhilipDukhov Means, a **worst** case scenario (e.g. animating a sort of progress-bar, which might be displayed for multiple minutes) might recomposition the whole screen every frame for a long period of time - Even, if the one and only element that actually needs the recomp is just a small part of the whole composition. So even in situations like this, there is no need to wrap those elements in a dedicated scope? I get the point that it would not take much time anyway, but isn't it still a matter of performance optimization? Maybe I'm still misunderstanding something. – Dominik Seemayr Feb 13 '22 at 17:05
  • 2
    I hope its not yet late for the discussion, but this is the only post I saw discussing about this topic, I also agree and wonder why this approach is uncommon. In my case I ended up scoping ALL my `composables` up to the `LazyList's` `itemsIndexed` composable, without doing so, my `scrolling` experience becomes the worst. So I now have this mental model that my `composables` will be enclosed into a function object and have their own world instead of them squishing each other if all of them are within a tree of a root/parent `inlined` composable such as `Row`, `Column`, `Box` etc – z.g.y Sep 07 '22 at 13:57
  • I agree with you @z.y I want to talk about a problem that I have. There are 4 input fields in a column, and each onTextChanged method recomposes these 4 input fields. In this case, a noticeable slowdown occurs. – Yusuf Yıldırım Nov 04 '22 at 17:38
  • There seems to be another approach (case-to-case basis though) I recently stumbled across [a post asking about @Stable](https://stackoverflow.com/questions/74211174/jetpack-compose-when-to-create-a-new-lambda-instance-in-composable#comment131415552_74211174), and the article discussing about it by Ben Trengrove [@Stable/@Immutable](https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8) – z.g.y Nov 15 '22 at 12:01

0 Answers0