从Android数据存储中检索数据并保存到全局变量
我正在制作android应用程序,我想在android从Android数据存储中检索数据并保存到全局变量,android,kotlin,datastore,Android,Kotlin,Datastore,我正在制作android应用程序,我想在android数据存储中保存配置。我已经创建了一个类,并且EditText中的值正确地保存到数据存储。我正在使用YouTube上的教程: 我可以在配置视图中正确查看配置(textview字段从数据存储中获取值): 此函数在EditText中显示实际配置,非常棒 但是我将用于连接MQTT服务器的配置,以及如何将配置保存到Varchar并用于另一个函数? 我在类中创建变量: class ConfigurationActivity : AppCompatActi
数据存储中保存配置。我已经创建了一个类,并且EditText
中的值正确地保存到数据存储
。我正在使用YouTube上的教程:
我可以在配置视图中正确查看配置(textview字段从数据存储中获取值):
此函数在EditText
中显示实际配置,非常棒
但是我将用于连接MQTT服务器的配置,以及如何将配置保存到Varchar并用于另一个函数?
我在类中创建变量:
class ConfigurationActivity : AppCompatActivity() {
private lateinit var binding: ActivityConfigurationBinding
private lateinit var mainViewModel: MainViewModel
var variMqttAddress = ""
(...)
在函数getvaluefromdatastore和savetovar
中,我想从DataStore
获取值并将其保存到variablevariMqttAddress
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
}
(.....)