updating Jetpack Compose UI from SQL Connector through ViewModel

Viewed 295

I have a price checker app. that requests the details of a product using its barcode. very simple.. i'm only in the first page.

I created the UI and SQL query and I can get the data from the server, however, I can't update the UI. there is something I'm not doing right for sure. but I'm still learning Kotlin so please be patient with me.

The function that request and display the data is this

@Composable
fun PriceChecker(viewModel: MainViewModel,context: Context) {
    var barcode by remember {
        mutableStateOf("")
    }
    val focusManager = LocalFocusManager.current
    Box(modifier = Modifier.size(250.dp)) {
        Column(
            modifier = Modifier
                .size(500.dp)
                .border(width = 2.dp, color = Color.White, shape = RoundedCornerShape(12.dp))
        ) {
            TextField(
                onValueChange = {
                    barcode = it
                },
                value = barcode,
                singleLine = true,
                keyboardActions = KeyboardActions(onDone = ({
                    //hidekeyboard
                    focusManager.clearFocus()
                  
  //get product details
                    viewModel.getDetails(barcode) <-- this
                  
                    //erasing text after sending barcode
                    barcode = ""
                })),
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
            )
            Text(text = viewModel.name) <-- needed value from SQLthrough ViewModel
            Text(text = viewModel.price)<-- needed value from SQL through ViewModel
        }
    }
}

In the viewmodel i have this simply


class MainViewModel:ViewModel() {

    var price= RepositorySQL().price


    var name = RepositorySQL().name


    fun getDetails(barcode:String){
        RepositorySQL().getProductDetails(barcode)
    }
}

i tried to use the mutablestateof() for the values but it also didn't update the UI

In the Sql connector i have it this way:

 var price by mutableStateOf("Product Name") //also var price = ""
    private set
    var name by mutableStateOf("Product Price") //also var name = ""
    private set

    val cls ="net.sourceforge.jtds.jdbc.Driver"
    var connection: Connection? = null


    fun getProductDetails(barcode: String){
        val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
        StrictMode.setThreadPolicy(policy)
        Class.forName(cls)
        connection = DriverManager.getConnection(newUrl, newUser, newPass)
        if (connection!=null){
            val statement = connection!!.createStatement()
            val result = statement.executeQuery("Select [ItemName],[Price] FROM [twisted].[dbo].[Inventory] WHERE [ItemNum] = '$barcode';")
            while (result.next()){
                name =  result.getString("ItemName")
                price = result.getDouble("Price").toString()
                Log.d(TAG, "Product name = ${name}") //values are printed correctly.
                Log.d(TAG, "Product Price = ${price}")//values are printed correctly.
                }
        }else{
            name = "Didn't get any data"
            Log.d(TAG, name)
        }
    }

the UI remains the same even when I update the values... I'm sure that the solution should be easy but I'm still learning...

1 Answers

For some reason you're creating RepositorySQL() on each line, that's gonna be all different objects

In your RepositorySQL you're using mutableStateOf with delegation. This makes price and name in MainViewModel plain strings, not states, so they're not gonna watch RepositorySQL values

To make MutableState private set you had to declare private MutableState and public State, like this:

class RepositorySQL {
    private val _price = mutableStateOf("Product Name")
    val price: State<String> = _price

    private val _name = mutableStateOf("Product Price")
    val name: State<String> = _name

    fun getProductDetails(t: String) {
        _price.value = "1"
        _name.value = "2"
    }
}

And in MainViewModel you can declare your values as delegates to RepositorySQL:

class MainViewModel:ViewModel() {
    private val repositorySQL = RepositorySQL()

    val price by repositorySQL.price

    val name by repositorySQL.name

    fun getDetails(barcode:String){
        repositorySQL.getProductDetails(barcode)
    }
}
Related