So, I'm using the Jetpack compose for my app and I have a state with a float value in the viewModel. This value can be updated outside of the slider; but also from the slider when the finger is lifted (I'd rather not update it while the user is still sliding the finger). I'd like the slider to reflect the value when it's updated from outside the slider; but when I let the slider internal state depend on it, the slider won't update whatsoever unless from the external state (there's no sliding motion). What am I doing wrong?
val sliderState = mutableStateOf(viewModel.state.value)
Slider(
modifier = Modifier
.fillMaxWidth(),
value = sliderState.value,
onValueChangeFinished = {
viewModel.state.value = sliderState.value
},
onValueChange = {
sliderState.value = it
},
)
CodePudding user response:
Just update the model value in the onValueChange
. You never need an internal state, since that causes ambiguity. Just follow the "single source of truth" principle.
Use this
Slider(
modifier = Modifier
.fillMaxWidth(),
value = viewModel.state.value,
onValueChange = {
viewModel.state.value = it
},
)
Ditch the internal variable.
No need to implement onValueFinished
.
It will be constantly updated in the model and read in the Composable at the same time. Also, if you won't update it continuously in the model, the slider won't slide in this scenario.
On the other hand, if you are implementing something like a slider that slides continuously but only updates a specific value when the user lifts there finger off the slider, use your exact code, but just apply a remember
to your internal variable.
val sliderState = remember { mutableStateOf(viewModel.state.value) }
Although, this is not something commonly required. If you are doing it for performance purposes, it is not required. Compose is built on top of this structure so it efficiently handles these rapid state changes.
CodePudding user response:
I didn't test it, but think something like this would work if viewModel.state is a StateFlow.
val sliderState = viewModel.state.collectAsState()
val localState = remember { mutableStateOf(sliderState.value) }
Slider(
modifier = Modifier
.fillMaxWidth(),
value = localState.value,
onValueChangeFinished = {
viewModel.state.value = localState.value
},
onValueChange = {
localState.value = it
}
)