如何在视图模型中将变量从编辑文本中获取到保存变量中?我想从MainActivity将以下变量获取到我的Viewmodel中val age = (binding.age.text.toString()).toInt()
我想我必须在活动中保存一个句柄状态,然后在视图模型中创建一个get((。我希望能得到一些指点。还是我错过了要点,应该在我的OnResume主要活动中使用它?
我在我的面纱模型中预先制定了以下步骤,这些步骤在轮换时有效,但年龄没有保存:
private const val TAG = "age"
//const val age = "age"
class hrViewModel(private val state: SavedStateHandle) : ViewModel() {
fun update(ageinput: Int): Int {
Log.d(TAG,"age", Exception())
val maxhr = 220 - ageinput
return maxhr
}
fun concatenate(vararg digits: Int): String {
return digits.joinToString(separator = " - ", transform = Int::toString)
}
fun target(agein: Int): String {
val bank = update(agein)
val high = bank * .5
val low = bank * .85
return concatenate(high.toInt(), low.toInt())
}
}```
如果您想使用SavedStateHandle
,通常的方法如下:
val age = savedStateHandle.getLiveData<Int>("age", 0) // or whatever default
fun setAge(age: Int) {
savedStateHandle["age"] = age
}
这样,您就可以通过该函数设置age值,该函数将其存储在SavedStateHandle
中,该值传播到LiveData
,在那里您可以用age.value
或observe
正常读取它。所以你只需要设置一次。
如果您有任何内部函数需要读取该值,只需执行
// a rare case where !! can make sense, since you -know- it won't be null
// since it has a default value
val currentAge = age.value!!
// do stuff with currentAge
或者,您可以遵循相同的反应模式,并使其在age
更新时,您的其他属性也会自动更新,例如
val maxHr: LiveData<Int> = age.map { age -> 220 - age }
你可以将这样的事情连锁起来,这样你就可以自动更新所有的值,只需制定其他事情发生变化时会发生什么的规则。
要更新age
值,只需调用setAge
即可。由于您正在尝试存储EditText
的内容,因此每当这些内容发生更改时,都需要更新ViewModel
。你可以用TextWatcher
来实现这一点——androidx.core-ktx
库有一些很好的函数,所以你可以实现你需要的回调:
binding.age.doAfterTextChanged { it?.toString()?.toIntOrNull()?.run(model::setAge) }
因此,现在,每当文本内容发生变化时,它都会尝试将其解析为Int
,并在VM上调用setAge
。
由于这些是LiveData
对象,您的UI可以observe
它们,并在更新时显示内容,包括首次连接Fragment
时。因此,如果你观察到age
LiveData
,你可以在文本框中显示它,当片段创建时,它会自动显示当前信息
// in the fragment, in onViewCreated is best since you need the viewLifecycleOwner
model.age.observe(viewLifecycleOwner) { age ->
ageText = age.toString()
if (binding.age.text.toString() != ageText) binding.age.setText(ageText)
}
这种检查是为了避免在EditText
已经显示该值时更新它。这一点很重要,因为记住,我们有一个TextWatcher
,每当EditText
的内容发生更改时,它就会更新age
。但由于更新age
触发了观察者,并且更新了EditText
的内容。。。你可以有一个无限的循环!
因此,这是打破这种循环的一种方法。如果新值是当前值,您也可以在LiveData
上调用distinctUntilChanged()
来获得一个不更新的值(或向观察者推送一个值(:
val age = savedStateHandle.getLiveData<Int>("age", 0).distinctUntilChanged()
这一切都有点尴尬,因为EditText
和其他Android视图小部件已经保持了自己的状态(如输入的文本(,但这就是你将ViewModel
中的状态推送到UI的方式,使其显示VM所说的应该显示的内容(这是目前推荐的方法(。这也使你能够加载存储的状态(比如从数据库或其他地方获取数据(,并让UI自动显示它,它只适用于