我正在使用ViewModel内部使用Livedata的双向数据指标来处理注册表单。
当填写字段时,需要将一些字段一起评估以获得有效性(以及整体形式),并且只有在一切正确的情况下才能启用提交按钮。
使用常规的Observable
对象并使用@Bindable
,只需注释所需的每个验证的'getter'函数,这将是简单的,并执行必要的验证步骤并返回每个功能内的适当结果。
,但我正在与Livedata合作。我想出了使用MediatoLiveData
的解决方案(请参阅下面的基本示例),但在我看来,就像还有另一种更好的方法。
class RegistrationViewModel : ViewModel() {
val email: MutableLiveData<String> by lazy { MutableLiveData<String>() }
val emailConf: MutableLiveData<String> by lazy { MutableLiveData<String>() }
val emailValid: MediatorLiveData<Boolean> = MediatorLiveData()
val emailChanged: (Any) -> Unit = cc@ {
//Obviously there is more validation needed but this is just an example
if (email.value != null && emailConf.value != null) {
emailValid.value = email.value.isNotEmpty() && emailConf.value.isNotEmpty() && email.value == emailConf.value
return@cc
}
emailValid.value = false
}
init {
emailValid.addSource(email, emailChanged)
emailValid.addSource(emailConf, emailChanged)
}
}
将其绑在UI上,例如,按钮的enabled
属性或标签的visibility
属性可以适当地绑定到emailValid
属性。
您的方法正确,但是代码有一些设计问题:
-
lazy
字段在init
部分中使用。田野变得懒惰 -
emailValid
字段可以以LiveData
暴露 验证可以封装在内部类中,但不需要
class RegistrationViewModel : ViewModel() { val email = MutableLiveData<String>() val emailConf = MutableLiveData<String>() @Suppress("UNCHECKED_CAST") val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply { val validator = Validator(::postValue) addSource(email, validator as Observer<String>) addSource(emailConf, validator as Observer<String>) } private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any> { override fun onChanged(ignored: Any?) { //Obviously there is more validation needed but this is just an example val email = email.value val emailConf = emailConf.value validationConsumer(when { email.isNullOrEmpty() -> false emailConf.isNullOrEmpty() -> false email == emailConf -> true else -> false }) } } }
如果您需要一些重型验证,则可以为emailValid
制作隐藏的Mutable字段并在后台验证完成时手动更新