https://kotlinlang.org logo
Title
l

Luca Nicoletti

04/04/2023, 9:59 AM
Is there anything wrong in using the
by remember
inside the
composable
function? Without it, the edit text field value has a weird behaviour.
class MyState(val text: String)
class MyViewModel(initialState: MyState) {
    internal val mState: MutableStateFlow<MyState> = MutableStateFlow(initialState)
    val state: StateFlow<MyState> = mState.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = initialState,
    )
}

@Composable
fun MyScreenState(state: MyState, onValueChange: (String) -> Unit) {
    var rememberText by remember { mutableStateOf(state.text) }
    OutlinedTextField(
        value = rememberText,
        onValueChange = { rememberText = it; onValueChange(it) }
    )
}
I feel like that
remember
is an extra-step, forcing us to do things “twice” on the ValueChange callback as well
a

abbic

04/04/2023, 10:03 AM
this looks odd to me, if your state is a stateflow then all you should need to do in your composable is val state by viewmodel.state.observeAsState()
l

Luca Nicoletti

04/04/2023, 10:03 AM
weird behaviour: typing and cancelling really quickly moves the cursor at random positions, and inputs are messed up
we have that already:
viewModel.state.collectAsState().value
is used as input of the
MyScreenState
a

abbic

04/04/2023, 10:05 AM
right
s

Stylianos Gakis

04/04/2023, 10:58 AM
Why do you have two sources of truth regarding what OutlinedTextField shows? Now you default the
rememberText
to the intial value of what the VM holds, and then keep a local state from that point on. Can you show how you had it before you added the
by
as you say? If you do that maybe it will show why it was having this weird behavior.
l

Luca Nicoletti

04/04/2023, 11:00 AM
Before the
remember
I had it inlined inside the
TextField( value = state.text
But this caused the weird behaviours I wrote above
s

Stylianos Gakis

04/04/2023, 11:10 AM
Since I don’t know exactly how all of your code looked like before by trying to piece things together, I will just say that it may be that this https://medium.com/androiddevelopers/effective-state-management-for-textfield-in-compose-d6e5b070fbe5 is what you were experiencing. The source of truth from which a TextField should be reading the text from should be mutableState optimally. And in any case, it should hopefully come from 1 source of truth instead of trying to sync one source locally and then one in the VM. Problems with having it in a StateFlow is that if you are introducing any sort of delays from changing it to emitting it you may be giving some delays which are not really supposed to happen with a TextField. All this is explained in very good detail in this blog. Give it a read and it may be what you are looking for.