SearchBar: adopt outside text changes in a side effect
SearchBar keeps a TextFieldValue so that the cursor ends up behind text that was changed from the outside (a search started by typing on a physical keyboard, or a reset search). That value was updated during composition, which is an anti-pattern: the value read earlier in the same composition is what gets drawn, so the write only schedules another recomposition pass of the search bar - and it can be dropped entirely if the composition does not complete. Do the same update in a SideEffect, after the composition. No behaviour change for the user.
This commit is contained in:
@@ -24,6 +24,7 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@@ -143,8 +144,14 @@ fun SearchBar(
|
|||||||
val textFieldValue = remember {
|
val textFieldValue = remember {
|
||||||
mutableStateOf(TextFieldValue(value, TextRange(value.length)))
|
mutableStateOf(TextFieldValue(value, TextRange(value.length)))
|
||||||
}
|
}
|
||||||
if (textFieldValue.value.text != value) {
|
// Characters the user typed are already in this value; onValueChange below keeps the cursor
|
||||||
textFieldValue.value = TextFieldValue(value, TextRange(value.length))
|
// where the user put it. Text that changed from the outside - the search was reset, or a
|
||||||
|
// character was inserted by the physical keyboard handler - is adopted here, with the cursor at
|
||||||
|
// the end. This must not write state during composition, so it runs in a side effect after it.
|
||||||
|
SideEffect {
|
||||||
|
if (textFieldValue.value.text != value) {
|
||||||
|
textFieldValue.value = TextFieldValue(value, TextRange(value.length))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherCard(
|
LauncherCard(
|
||||||
|
|||||||
Reference in New Issue
Block a user