从 Android DataStore 中检索数据并保存到全局变量
Retrieve data from Android DataStore and save to global var
我正在制作 android 应用程序,我想在 Android DataStore
中保存配置。我创建了一个 class,EditText
中的值正确保存到 DataStore
。我使用来自 YouTube 的教程:https://www.youtube.com/watch?v=hEHVn9ATVjY
我可以在配置视图中正确查看配置(textview 字段从数据存储中获取值):
private fun showConfigurationInForm(){
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
binding.conMqttAddress.setText(mqqtAdress)
}
}
此函数在 EditText
中显示实际配置,这很棒
但是我将用于连接到 MQTT 服务器的配置,如何将配置保存到 Varchar 并用于另一个功能?
我在 class:
中创建 var
class ConfigurationActivity : AppCompatActivity() {
private lateinit var binding: ActivityConfigurationBinding
private lateinit var mainViewModel: MainViewModel
var variMqttAddress = ""
(...)
在函数 getValueFromDatastoreAndSaveToVar
中,我想获取 DataStore
中的值并将其保存到变量 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::
请帮忙
当 flows
与 DataStore
一起使用时,value
将被异步获取,这意味着您不会立即获得该值,请尝试在 observe
方法中打印日志,然后创建你的 MQttClient
和 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())
}
}
另一种方法是在流上使用 collect/first
来阻止获取,但它需要在 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
更新
如果您有来自不同 LiveData
个实例的多个值,那么您可以创建一个类似于 validateParatmers()
的方法,该方法将在创建实例之前检查所有参数,例如
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
}
}
在存储库 class 中,我为每个值创建了一个流
//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
}
(.....)
现在的问题是我做对了吗?
现在如何仅当我在变量中包含所有参数时才创建 MQttClient?
可以让应该创建 MQQTClient 的函数休眠直到异步函数为变量赋值吗?
我正在制作 android 应用程序,我想在 Android DataStore
中保存配置。我创建了一个 class,EditText
中的值正确保存到 DataStore
。我使用来自 YouTube 的教程:https://www.youtube.com/watch?v=hEHVn9ATVjY
我可以在配置视图中正确查看配置(textview 字段从数据存储中获取值):
private fun showConfigurationInForm(){
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
mainViewModel.readMqttAddressFlow.observe(this) { mqqtAdress ->
binding.conMqttAddress.setText(mqqtAdress)
}
}
此函数在 EditText
中显示实际配置,这很棒
但是我将用于连接到 MQTT 服务器的配置,如何将配置保存到 Varchar 并用于另一个功能? 我在 class:
中创建 varclass ConfigurationActivity : AppCompatActivity() {
private lateinit var binding: ActivityConfigurationBinding
private lateinit var mainViewModel: MainViewModel
var variMqttAddress = ""
(...)
在函数 getValueFromDatastoreAndSaveToVar
中,我想获取 DataStore
中的值并将其保存到变量 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::
请帮忙
当 flows
与 DataStore
一起使用时,value
将被异步获取,这意味着您不会立即获得该值,请尝试在 observe
方法中打印日志,然后创建你的 MQttClient
和 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())
}
}
另一种方法是在流上使用 collect/first
来阻止获取,但它需要在 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
更新
如果您有来自不同 LiveData
个实例的多个值,那么您可以创建一个类似于 validateParatmers()
的方法,该方法将在创建实例之前检查所有参数,例如
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
}
}
在存储库 class 中,我为每个值创建了一个流
//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
}
(.....)
现在的问题是我做对了吗? 现在如何仅当我在变量中包含所有参数时才创建 MQttClient?
可以让应该创建 MQQTClient 的函数休眠直到异步函数为变量赋值吗?