MediatorLiveData直接从ViewModel绑定到View



当4个EditText的字符数超过X并且电子邮件有效时,我试图启用/禁用一个按钮(忽略xml,仍在应用样式):

<Button
android:id="@+id/fragment_login_button"
android:fontFamily="@font/montserrat_regular"
android:layout_marginTop="20dp"
android:textColor="@android:color/white"
android:background="@drawable/button_primary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:enabled="@{viewModel.createAccountDetailsValid}"
android:layout_marginRight="20dp"
android:text="create account "
android:onClick="@{(theView) -> handler.onCreateClick(theView, viewModel)}"
app:layout_constraintTop_toBottomOf="@id/fragment_login_companyText"
/>

我使用MediatorLiveData和按钮所依赖的4个MutableLiveData使其工作,但我发现这样做违背了MVVM标准,但这是唯一的工作方式,因为MediatorLiveData只允许addSource。如果至少有1个观察者,请查看代码:

在我的视图模型上:

//USER DATA
val email: MutableLiveData<String> = MutableLiveData()
val name: MutableLiveData<String> = MutableLiveData()
val surname: MutableLiveData<String> = MutableLiveData()
val company: MutableLiveData<String> = MutableLiveData()
val createAccountDetailsValid: MediatorLiveData<Boolean> = MediatorLiveData()
fun populateMediator(owner: LifecycleOwner) {
createAccountDetailsValid.observe(owner, Observer {  })
createAccountDetailsValid.addSource(email) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(name) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(surname) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(company) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
}
private fun isCreateAccountDetailsValid() : Boolean {
if(email.value == null || name.value == null || surname.value == null || company.value == null) return false
return android.util.Patterns.EMAIL_ADDRESS.matcher(email?.value!!).matches() && name.value?.length!! >= 3 && surname.value?.length!! >= 3 && company.value?.length!! >= 3
}

在我的碎片上:

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container,false)
viewModel = ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel::class.java)
binding.viewModel = viewModel
binding.handler = LoginHandler()
binding.setLifecycleOwner(this)
viewModel.setLifecycleOwner(this as LifecycleOwner)
return binding.root
}

就像我说的那样,它正在工作,但ViewModel引用了View(LifecycleOwner),是的,我可以将空的观察者放在Fragment上,不需要将LifecycleOwner传递给ViewModel,但仍然感觉不对劲,也许我在这里有点完美主义,但我敢打赌还有另一种直接从ViewModel绑定的方法,而不必设置isEnable来观察片段中的MediatorLiveData?

谢谢!

有Blackbelt评论吗?我本应该做错什么,但在努力使问题正常工作的同时,却使问题复杂化并得到解决。

他说数据绑定观察到了吗?你可以像我一样在viewModelinit上添加Source,并使其工作:

val createAccountResult: MutableLiveData<Resource<Void>> = MutableLiveData()
val loginResult: MutableLiveData<Resource<Void>> = MutableLiveData()
//USER DATA
val email: MutableLiveData<String> = MutableLiveData()
val name: MutableLiveData<String> = MutableLiveData()
val surname: MutableLiveData<String> = MutableLiveData()
val company: MutableLiveData<String> = MutableLiveData()
var createAccountDetailsValid: MediatorLiveData<Boolean> = MediatorLiveData()
init {
createAccountDetailsValid.addSource(email) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(name) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(surname) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
createAccountDetailsValid.addSource(company) {
createAccountDetailsValid.value = isCreateAccountDetailsValid()
}
}

感谢您的帮助@Blackbelt

相关内容

  • 没有找到相关文章

最新更新