Home > OS >  Why can't a mutableStateOf based data class update UI automatically in Android Studio?
Why can't a mutableStateOf based data class update UI automatically in Android Studio?

Time:02-03

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)
    }
}
  •  Tags:  
  • Related