使用Kotlin查看模型和活动



如何在视图模型中将变量从编辑文本中获取到保存变量中?我想从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.valueobserve正常读取它。所以你只需要设置一次。


如果您有任何内部函数需要读取该值,只需执行

// 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时。因此,如果你观察到ageLiveData,你可以在文本框中显示它,当片段创建时,它会自动显示当前信息

// 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自动显示它,它只适用于

最新更新