Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Android数据存储中检索数据并保存到全局变量_Android_Kotlin_Datastore - Fatal编程技术网

从Android数据存储中检索数据并保存到全局变量

从Android数据存储中检索数据并保存到全局变量,android,kotlin,datastore,Android,Kotlin,Datastore,我正在制作android应用程序,我想在android数据存储中保存配置。我已经创建了一个类,并且EditText中的值正确地保存到数据存储。我正在使用YouTube上的教程: 我可以在配置视图中正确查看配置(textview字段从数据存储中获取值): 此函数在EditText中显示实际配置,非常棒 但是我将用于连接MQTT服务器的配置,以及如何将配置保存到Varchar并用于另一个函数? 我在类中创建变量: class ConfigurationActivity : AppCompatActi

我正在制作android应用程序,我想在android
数据存储中保存配置。我已经创建了一个类,并且
EditText
中的值正确地保存到
数据存储
。我正在使用YouTube上的教程: 我可以在配置视图中正确查看配置(textview字段从数据存储中获取值):

此函数在
EditText
中显示实际配置,非常棒

但是我将用于连接MQTT服务器的配置,以及如何将配置保存到Varchar并用于另一个函数? 我在类中创建变量:

class ConfigurationActivity : AppCompatActivity() {

    private lateinit var binding: ActivityConfigurationBinding

    private lateinit var mainViewModel: MainViewModel

    var variMqttAddress = ""
    (...)
在函数
getvaluefromdatastore和savetovar
中,我想从
DataStore
获取值并将其保存到variable
variMqttAddress

private fun getValueFromDatastoreAndSaveToVar(){
    mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
    mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
        variMqttAddress = mqqtAdress
    }
}
但它不起作用。调试时,var中有一个空值

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

___________

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

请帮助

当将
数据存储
一起使用时,
将异步获取,这意味着您不会立即获得值,请尝试在
观察
方法中打印日志,然后使用url创建
MQttClient

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())
    }
}
另一种方法是在流上使用,
collect/first
来阻止get,但它需要位于
coroutinescope

快速提示:我认为您可以全局初始化一次
mainViewModel
,并在所有方法中访问它,而不是在每个方法中重新分配它们 方法。似乎多余

更新

如果有多个值来自不同的
LiveData
实例,则可以创建一个类似
validateParamers()
的方法,该方法将在创建类似的实例之前检查所有参数

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  
}

谢谢你的帮助

我之前没有添加,除了配置中MQQT服务器的地址之外,它还存储端口、用户和密码

我认为我做错了什么,在每个YouTube教程中都会显示如何“下载”一个配置参数。现在检索数据的函数如下所示:

private fun getValueFromDatastoreAndSaveToVar(){
        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
            variMqttAddress = mqqtAdress
            Log.d(TAG, "variMqttAddress:: $variMqttAddress")
        }
        mainViewModel.readMqttPortFlow.observe(this) {mqttPort ->
            variMqttPass = mqttPort.toString()
        }
        mainViewModel.readMqttUserFlow.observe(this) { mqttUser ->
            variMqttUser = mqttUser
        }
        mainViewModel.readMqttPassFlow.observe(this) { mqttPass ->
           variMqttPass = mqttPass
        }
}
在repository类中,我为每个值创建一个流

    //Create MQTT Address flow
    val readMqttAddressFlow: Flow<String> = dataStore.data
        .catch { exception ->
            if(exception is IOException){
                Log.d("DataStore", exception.message.toString())
                emit(emptyPreferences())
            }else {
                throw exception
            }
        }
        .map { preference ->
            val mqqtAdress = preference[PreferenceKeys.CON_MQTT_ADDRESS] ?: "none"
            mqqtAdress
        }

    //Create MQTT Port flow
    val readMqttPortFlow: Flow<Int> = dataStore.data
        .catch { exception ->
            if(exception is IOException){
                Log.d("DataStore", exception.message.toString())
                emit(emptyPreferences())
            }else {
                throw exception
            }
        }
        .map { preference ->
            val mqqtPort = preference[PreferenceKeys.CON_MQTT_PORT] ?: 0
            mqqtPort
        }

(.....)

//创建MQTT地址流
val readMqttAddressFlow:Flow=dataStore.data
.catch{异常->
if(异常为IOException){
Log.d(“数据存储”,exception.message.toString())
emit(emptyPreferences())
}否则{
抛出异常
}
}
.map{首选项->
val mqtAddress=首选项[PreferenceKeys.CON_MQTT_地址]?:“无”
MQQTAddress
}
//创建MQTT端口流
val readMqttPortFlow:Flow=dataStore.data
.catch{异常->
if(异常为IOException){
Log.d(“数据存储”,exception.message.toString())
emit(emptyPreferences())
}否则{
抛出异常
}
}
.map{首选项->
val mqqtPort=首选项[PreferenceKeys.CON_MQTT_PORT]?:0
mqqtPort
}
(.....)
现在的问题是我做得对吗? 现在,如何仅在变量中包含所有参数时创建MQttClient


在asychnronic函数将值分配给变量之前,是否可以对本应创建MQQTClient的函数执行一些休眠操作?

我在另一篇文章中添加了一个问题,这里没有足够的字符。
ViewModel
公开流或LiveData吗?正如您所观察到的,在类
MainViewModel
中收集而不是
readMqttAddressFlow
中,我有
private val repository=DataStoreRepository(application)
val readMqttAddressFlow=repository.readMqttAddressFlow.asLiveData()
非常适合您使用Livedata,将Flow的名称更改为LiveData,这很混乱,我已经更新了答案。希望它能帮上忙,它能起作用。只有当所有变量都存在时,我才运行“connectMQTT”函数。我只是有个问题。这是正确的操作吗?我有一个简单的应用程序,只有3个活动。同样,它在一些复杂的应用程序中工作吗?例如,他持有的某个电子邮件客户端的服务器地址、密码。。很多代码,在每个活动中都必须运行fun getValueFromDatastoreAndSaveToVar()?理想情况下,所有需要的信息都是捆绑在一起的单个响应/LiveData的一部分
    //Create MQTT Address flow
    val readMqttAddressFlow: Flow<String> = dataStore.data
        .catch { exception ->
            if(exception is IOException){
                Log.d("DataStore", exception.message.toString())
                emit(emptyPreferences())
            }else {
                throw exception
            }
        }
        .map { preference ->
            val mqqtAdress = preference[PreferenceKeys.CON_MQTT_ADDRESS] ?: "none"
            mqqtAdress
        }

    //Create MQTT Port flow
    val readMqttPortFlow: Flow<Int> = dataStore.data
        .catch { exception ->
            if(exception is IOException){
                Log.d("DataStore", exception.message.toString())
                emit(emptyPreferences())
            }else {
                throw exception
            }
        }
        .map { preference ->
            val mqqtPort = preference[PreferenceKeys.CON_MQTT_PORT] ?: 0
            mqqtPort
        }

(.....)