how to tell the UI to change the Values to a computed property

105 views Asked by At

usually in iOS i will do a didSet but Kotlin does not provide the same, how can I do Such a thing.

`

val dnValues = stringArrayResource(R.array.dn_values_array)

val pnValuesSteel = stringArrayResource(R.array.pn_values_array_full)
val pnValuesGray = stringArrayResource(R.array.pn_values_array_gray_iron)
val pnValuesDuctile = stringArrayResource(R.array.pn_values_array_ductile_iron)

var pnValues = pnValuesGray

val materialValues = stringArrayResource(R.array.materials_array)

val newMaterial: (String) -> Unit = { material ->

    when (material) {
        materialValues[0] -> {
            pnValues = pnValuesGray
        }

        materialValues[1] -> {
            pnValues = pnValuesDuctile
        }

        materialValues[2] -> {
            pnValues = pnValuesSteel
        }
    }
}`

when I debug the code I see the pnValues change the way I want, but the UI never refresh on the edit.

4

There are 4 answers

0
Mahameed On BEST ANSWER

I have tried the previous comments, because the Values get stuck on the remembered ones and the Custom picker won't work.

val dnValues = stringArrayResource(R.array.dn_values_array)

val pnValuesSteel = stringArrayResource(R.array.pn_values_array_full)
val pnValuesGray = stringArrayResource(R.array.pn_values_array_gray_iron)
val pnValuesDuctile =  stringArrayResource(R.array.pn_values_array_ductile_iron)

val materialValues = stringArrayResource(R.array.materials_array)

var assignedMaterial by remember { mutableStateOf("") }

val newMaterial: (String) -> Unit = { material ->

    when (material) {
        materialValues[0] -> {
            assignedMaterial = material
        }

        materialValues[1] -> {
            assignedMaterial = material
        }

        materialValues[2] -> {
            assignedMaterial = material
        }
    }
}

what I did was, just removing the pnValuesSteel, Gray, Ductile and set the correct one depending on the material which I retrieve from the chosen one on the picker. setting the pnValuesSteel, Gray, Ductile (values) I have done it in the same scope where it should be assigned. see below

        CircularList(
                    width = 60.dp,
                    itemHeight = 50.dp,
                    items = when (assignedMaterial) {
                        materialValues[0] -> {
                            pnValuesGray
                        }

                        materialValues[1] -> {
                            pnValuesDuctile
                        }

                        materialValues[2] -> {
                            pnValuesSteel
                        }
                        else ->{
                            pnValuesGray
                        }
                    }

now it works perfectly.

any comments on the solution would be appreciated.

1
user1425217 On

Just like BenjyTec answered.

  1. You have to declare the pnValues as MutableState.
  2. Your Composable has to use the value from pnValues.
var pnValues by remember { mutableStateOf(pnValuesGray) }

//makes your composable observe the value from pnValues
YourComposable(pnValues)

@Composable
fun YourComposable(value: String) {
    Text(value)
}

Then whenever pnValues changed its value, the Text composable will recompose with the latest value.

1
BenjyTec On

Try out the following variable declaration:

var pnValues by remember { mutableStateOf(pnValuesGray) }  

If you assign a new value to pnValues, the UI should change accordingly. In Jetpack Compose, you need to remember all variables that the Composables should observe the changes from.
Also see the documentation about State in Jetpack Compose.

0
Jakub Kostka On

I think you're misunderstanding how JetPack Compose works. In most cases, you no longer update variables and states by methods (update, set, get, etc.).

Instead, there are mutableStates - val myState = mutableStateOf</variable type/>(/initial state value, such as from a constructor/)

Docs for states in JetPack Compose: https://developer.android.com/jetpack/compose/state#managing-state

Any change to the variable myState updates the UI whenever you subscribe to it, by using it for example in Text(modifier = Modifier.background(color = myState.value)).

The value can be then changed by anything you desire.

Easiest example of variable change would be from a button click, as following:

   Button(
        onClick = {
             myState.value = /whatever value you declared in the mutableStateOf/
        }
   ) {
        Text(text = "Click me to update variable")
   }

In case of some variable coming from API, which should update our variable, use

   LaunchedEffect(/to what change are we subscribing? - such as viewModel.variableX.value/) { 
        viewModel.variableX.collect {  
              myState.value = /whatever value you declared in the mutableStateOf/
        }
   }

Docs for LaunchedEffect: https://developer.android.com/jetpack/compose/side-effects#launchedeffect

Note, that any UI change will also change all the variables into their initial states because they are not labeled as remembered. Such thing is crucial when using mutableStates. It can be achieved as following:

val myState = remember(/on what variable is the remember broken - such as value from a constructor/) { 
       mutableStateOf</variable type/>(/initial state value, such as from a constructor/)
}

Docs for State holders: https://developer.android.com/topic/architecture/ui-layer/stateholders