The var myData= mutableStateOf(MyData()) is based a data class, I think the UI component associated with it can be updated automatically when it changed.
I run the following code, I hope the text of Currect and Max on the UI can be updated automatically after I click "Start" button, but UI doesn't update, why?
class HandleMeter: ViewModel() {
var temp= mutableStateOf(0)
data class MyData(
var current:Int=1,
var max:Int=100
)
var myData= mutableStateOf(MyData())
private var myJob: Job?=null
private fun soundDbFlow(period: Long=100) = flow {
while (true) {
val data =(0..1000).random()
emit(data)
delay(period)
}
}
fun calCurrentAsynNew() {
myJob?.cancel()
myJob = viewModelScope.launch(Dispatchers.IO) {
soundDbFlow().collect {setMyData(it)}
}
}
fun setMyData(input: Int) {
temp.value=input //Only for test
myData.value.current = input
if (input > myData.value.max) {
myData.value.max = input
}
//myData.value= MyData(myData.value.current, myData.value.max) Doesn't work
//myData = mutableStateOf(MyData(myData.value.current, myData.value.max) ) Doesn't work
}
}
@Composable
fun Greeting(handleMeter: HandleMeter) {
var myData = handleMeter.myData
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Current ${myData.value.current}")
Text(text = "Max ${myData.value.max}")
Button(
modifier = Modifier.padding(vertical = 24.dp),
onClick = { handleMeter.calCurrentAsynNew() }
) {
Text("Start")
}
}
}
CodePudding user response:
You should update the value of myData state directly for your composables to recompose instead of updating its properties. Also you can use Kotlin delegates to help clean up the code a little bit by getting rid of using .value all the time.
data class MyData(
val current: Int = 1, // Use val instead of var
val max: Int = 100
)
var myData by mutableStateOf(MyData())
fun setMyData(input: Int) {
myData = myData.copy(current = input)
if (input > myData.max) {
myData = myData.copy(max = input)
}
}
