Hey there :wave: When searching for composable scr...
# compose
g
Hey there 👋 When searching for composable screens that could be recomposing unnecessarily I found out a screen which is basically a
LazyColumn
with mostly
TextFields
inside I noticed they were all recomposing on every key stroke for any of the fields. So if I type in something in the first field, the other fields, even though they did not change their value, will also recompose. After experimenting a bit I pinned it down to using the
onFocusChanged
modifier for these text fields. After removing the
onFocusChanged
modifier the text fields seem to skip composition. Is this the expected behaviour ? Quick repro (I am using the the recomposeHighlighter to visualize recompositions):
Copy code
val state = remember {
      List(20) { it to "" }.toMutableStateMap()
    }

    LazyColumn(Modifier.fillMaxSize()) {
      itemsIndexed(state.values.toList()) { index, string ->
        TextField(
          value = string,
          onValueChange = { state[index] = it },
          modifier = Modifier
            .recomposeHighlighter()
            .onFocusChanged {  }
        )
      }
    }
👀 2
m
If the onfocuschanged lambda content calls something not stable, it is possible it may be the cause. What are you doing in onfocuschanged?
g
I also thought that but it happens even when it is empty, like in the example I provided
m
Hm ok. Is that composable declared inside a fragment by any chance?
p
@Guilherme Almeida It is because it can’t omit recomposition as long as it’s not in its own composable
With one big composable, its inputs seem to be everything that’s before that code
g
Ah interesting 🤔 In the app the text field is passed in through two composables (by passing a composable lambda), but the composable itself is created in the main composable I guess
I guess if you try to pass in the modifier from the main composable it will also recompose right?
m
ToMutableStateMap, is that stable?
g
I can test it a bit more tomorrow, thank you very much 🙏
I would expect it to be, and without the modifier recomposition occurs as expected 🤔
m
Oh. The second item recompose is the focus change it makes sense
g
So after testing it a bit more the problem seems to be where the
onFocusChanged
modifier is created, so If the modifier is created in the main composable it recomposes for every new state there, if it is inside its own composable then it only recomposes when the state has changed. Wrapping the modifier with
remember
also works, but does not seem ideal