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 观察 Fragment 中的 MediatorLiveData?

谢谢!

伊曼纽尔朋友

有黑带评论我应该做错了什么,最终在尝试使其工作时使问题复杂化并解决了问题。

他有没有说过数据绑定观察,你可以像我一样在 viewModel init 上 addSource 并让它工作:

 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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法将ViewModel绑定到View

来自分类Dev

将viewModel属性绑定到MvvmCross中的view属性

来自分类Dev

将viewModel属性绑定到MvvmCross中的view属性

来自分类Dev

从ControlTemplate绑定到ViewModel

来自分类Dev

绑定到ViewModel的集合

来自分类Dev

从ControlTemplate绑定到ViewModel

来自分类Dev

将View绑定到ViewModel时WPF中的ToolTip内存泄漏

来自分类Dev

如何将View控件正确绑定到ViewModel列表(WPF MVVM)

来自分类Dev

ViewModel 和 View 未绑定到列表框中的用户控件

来自分类Dev

在DataGrid上绑定View和ViewModel

来自分类Dev

MVVM View vs ViewModel 绑定问题

来自分类Dev

从ViewModel绑定到反向ObservableCollection

来自分类Dev

MultiValueConverter无法绑定到ViewModel

来自分类Dev

WPF绑定到ViewModel从单独

来自分类Dev

从ViewModel绑定到反向ObservableCollection

来自分类Dev

将 ViewModel 绑定到 CustomControl

来自分类Dev

在WPF中从View触发事件到ViewModel

来自分类Dev

将模型绑定到ViewModel(WPF)

来自分类Dev

将命令绑定到子ViewModel

来自分类Dev

将AngularJS绑定到MVC ViewModel属性

来自分类Dev

如何将TreeView绑定到ViewModel?

来自分类Dev

将事件绑定到ViewModel:扩展文章

来自分类Dev

将selectlistitems绑定到ViewModel的正确方法

来自分类Dev

将ComboBox绑定到Model / ViewModel

来自分类Dev

将ViewModel绑定到多个窗口

来自分类Dev

将UserControl的DataContext绑定到子ViewModel

来自分类Dev

Knockout.js数据绑定到ViewModel

来自分类Dev

使用IsSynchronizedWithCurrentItem绑定到ViewModel中的集合

来自分类Dev

绑定到ViewModel和CodeBehind中的属性