Search code examples
androidkotlindatastore

Retrieve data from Android DataStore and save to global var


I am making android app and I wants save configuration in Android DataStore. I have created a class and the values from EditText are correct save to DataStore. I using tutorial from YouTube: https://www.youtube.com/watch?v=hEHVn9ATVjY I can view the configuration in the config view correctly (textview fields get the value from the datastore):

private fun showConfigurationInForm(){
    mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
    mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
        binding.conMqttAddress.setText(mqqtAdress)
    }
}

This function show actual config in EditText, and this is great

But the config I will use to connect to MQTT Server, and how can I save the config to Varchar and use to another function? I create var in class:

class ConfigurationActivity : AppCompatActivity() {

    private lateinit var binding: ActivityConfigurationBinding

    private lateinit var mainViewModel: MainViewModel

    var variMqttAddress = ""
    (...)

And in function getValueFromDatastoreAndSaveToVar I want to get and save values from DataStore to variable variMqttAddress

private fun getValueFromDatastoreAndSaveToVar(){
    mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
    mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
        variMqttAddress = mqqtAdress
    }
}

but it doesn't work. when debugging I have an empty value in var

 Log.d(TAG, "variMqttAddress:: $variMqttAddress")

___________

2021-02-16 12:42:20.524 12792-12792 D/DEBUG: variMqttAddress:: 

Please help


Solution

  • When using flows with DataStore, value will be fetched asynchronously meaning you wont have the value right away, try printing log inside observe method and then create your MQttClient with the url

    private fun getValueFromDatastoreAndSaveToVar(){
        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
            variMqttAddress = mqqtAdress
            //varImqttAddress will be available at this point
            Log.d(TAG, "variMqttAddress:: $variMqttAddress")
            val mqttClient = MqttAsyncClient(varImqttAddress, clientId, MemoryPersistence())
        }
    }
    

    other way is to use, collect/first on flows for blocking get but it requires to be inside a coroutinescope

    Quick Tip: I think you can initialise mainViewModel globally once and access it in all methods instead of reassigning them in each method. Seems redundant

    UPDATE

    If you have multiple values coming from different LiveData instances, then you can create a method something like validateParatmers(), which will have checks for all the parameters before creating instance like

    private fun getValueFromDatastoreAndSaveToVar(){
        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
    
        mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
            variMqttAddress = mqqtAdress
            Log.d(TAG, "variMqttAddress:: $variMqttAddress")
            validateParametersAndInitMqtt() //add checks after observing ever livedata
        }
        mainViewModel.readMqttPortFlow.observe(this) {mqttPort ->
            variMqttPass = mqttPort.toString()
            validateParametersAndInitMqtt()
        }
        mainViewModel.readMqttUserFlow.observe(this) { mqttUser ->
            variMqttUser = mqttUser
            validateParametersAndInitMqtt()
        }
        mainViewModel.readMqttPassFlow.observe(this) { mqttPass ->
           variMqttPass = mqttPass
            validateParametersAndInitMqtt()
        }
    }
    
    private fun validateParametersAndInitMqtt(){
        if(variMqttAddress.isEmpty() || variMqttPass.isEmpty()
                || variMqttUser.isEmpty() || variMqttPass.isEmpty()){
              //if any one is also empty, then don't proceed further
              return
         }
         //create socket instance here, all your values will be available  
    }