抽象 ViewModel 不更新 LiveData Android MVVM

Posted

技术标签:

【中文标题】抽象 ViewModel 不更新 LiveData Android MVVM【英文标题】:Abstract ViewModel Not Updating LiveData Android MVVM 【发布时间】:2020-05-17 08:16:12 【问题描述】:

你好朋友,我有一个抽象的 ViewModle EmployeeViewModel 我必须重用 EmployeeViewModel ,这里是

abstract class EmployeeViewModel : ViewModel() 
    /** Form fields */
    var name                = MutableLiveData("")
    var username            = MutableLiveData("")
    var password            = MutableLiveData("")
    var conformPassword     = MutableLiveData("")
    var mobile              = MutableLiveData("")
    var designation         = MutableLiveData("")
    var employee: Employee? = null

现在我创建了一个名为 AddEmployeeViewModel 的子 ViewModel,用于添加员工,这里是

class AddEmployeeViewModel : EmployeeViewModel() 

fun onClickAddEmployee(view: View)
    when
        name.value.isNullOrEmpty()              -> view.context.toast("Please enter name")
        mobile.value.isNullOrEmpty()            -> view.context.toast("Please enter mobile number")
        mobile.value!!.length != 10             -> view.context.toast(
            "Mobile number should contain 10 digits"
        )
        designation.value == "--- Choose ---"   -> view.context.toast("Please select designation")
        password.value.isNullOrEmpty()          -> view.context.toast("Please enter password")
        conformPassword.value != password.value -> view.context.toast("Password did not match")
        else ->

        
    


onClickAddEmployee(view: View) 被调用时,我可以看到所有字段都是空的,但我已经用这个布局绑定了所有字段

<?xml version="1.0" encoding="utf-8"?>
<layout
tools:ignore="ContentDescription,HardcodedText,PrivateResource,RtlHardcoded"
xmlns:tools="http://schemas.android.com/tools">
<!--region Data    -->
<data>
    <variable
        name="viewModel"
        type="com.aseemsalim.mvvmtestapp.ui.employee.EmployeeViewModel" />
</data>
<!--endregion    -->
<!--region Form    -->
<LinearLayout
    android:focusable="true"
    android:focusableInTouchMode="true"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_>
    <!--region Name-->
    <com.google.android.material.textfield.TextInputLayout
        style="@style/TextInputLayoutStyle">
        <com.google.android.material.textfield.TextInputEditText
            android:layout_
            android:layout_
            android:text="@=viewModel.name"
            android:hint="Name" />
    </com.google.android.material.textfield.TextInputLayout>
    <!--endregion-->
    <!--region Mobile-->
    <com.google.android.material.textfield.TextInputLayout
        style="@style/TextInputLayoutStyle">
        <com.google.android.material.textfield.TextInputEditText
            android:text="@=viewModel.mobile"
            android:layout_
            android:layout_
            android:inputType="number"
            android:hint="Mobile"/>
    </com.google.android.material.textfield.TextInputLayout>
    <!--endregion-->
    <!--region Designation-->
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_
        android:layout_>
        <Spinner
            selectedItem="@=viewModel.designation"
            android:background="@drawable/spinner_background"
            android:layout_
            android:layout_
            android:layout_margin="8dp"
            android:paddingTop="16dp"
            android:paddingBottom="16dp"
            android:entries="@array/designations"/>
        <TextView
            android:paddingLeft="4dp"
            android:paddingRight="4dp"
            android:background="@android:color/background_light"
            android:layout_
            android:layout_
            android:text="Designation"
            android:textColor="@color/mtrl_outlined_stroke_color"
            android:layout_marginLeft="16dp"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    <!--endregion-->
    <!--region Username-->
    <com.google.android.material.textfield.TextInputLayout
        style="@style/TextInputLayoutStyle">
        <com.google.android.material.textfield.TextInputEditText
            android:text="@=viewModel.username"
            android:layout_
            android:layout_
            android:hint="Username"/>
    </com.google.android.material.textfield.TextInputLayout>
    <!--endregion-->
    <!--region Password-->
    <com.google.android.material.textfield.TextInputLayout
        style="@style/TextInputLayoutStyle">
        <com.google.android.material.textfield.TextInputEditText
            android:text="@=viewModel.password"
            android:layout_
            android:layout_
            android:inputType="textPassword"
            android:hint="Password"/>
    </com.google.android.material.textfield.TextInputLayout>
    <!--endregion-->
    <!--region Conform Password-->
    <com.google.android.material.textfield.TextInputLayout
        style="@style/TextInputLayoutStyle">
        <com.google.android.material.textfield.TextInputEditText
            android:text="@=viewModel.conformPassword"
            android:layout_
            android:layout_
            android:inputType="textPassword"
            android:hint="Conform Password"/>
    </com.google.android.material.textfield.TextInputLayout>
    <!--endregion-->
</LinearLayout>
<!--endregion    -->
</layout>

这是我的ActivityAddEmployee 布局代码,我在此处包含了员工代码

<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
    <variable
        name="viewModel"
        type="com.aseemsalim.mvvmtestapp.ui.hr.AddEmployeeViewModel" />
</data>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:orientation="vertical"
    android:layout_
    tools:context=".ui.hr.AddEmployee">

    <include layout="@layout/employee"/>
    <Button
        android:onClick="@viewModel::onClickAddEmployee"
        android:layout_margin="8dp"
        android:layout_
        android:layout_
        android:background="@color/colorPrimary"
        android:text="ADD EMPLOYEE"/>

</LinearLayout>
</layout>

请帮帮我

【问题讨论】:

【参考方案1】:

这里的问题是您的 viewModel 没有从您的父布局传递到包含的布局。 尝试添加类似的内容:

<include layout="@layout/employee"
viewModel="@viewModel"/>

这应该可以解决您的问题。

【讨论】:

它不工作你可以看到我已经创建了 EmployeeViewModel 作为抽象类我想重用它 我不明白为什么需要 AddEmployeeViewModel,EmployeeViewModel 可以包含与员工相关的所有操作。此外,您不能直接使用抽象类,您需要一个扩展此抽象并实现其方法的类。我建议在两种布局上都使用 EmployeeViewModel。 这里我将 AddEmployeeViewModel 扩展到 EmployeeViewModel 是的,但是员工布局应该使用 AddEmployeeViewModel 而不是 EmployeeViewModel

以上是关于抽象 ViewModel 不更新 LiveData Android MVVM的主要内容,如果未能解决你的问题,请参考以下文章

使用 Kotlin 从 Android 上 ViewModel 中的 LiveData 更新 ListView 中的元素

Android jetpack room+ViewModel+liveData 数据自动更新

Android Studio 之 ROM, LiveData+ViewModel+AsyncTask+Repository

学会使用LiveData和ViewModel,我相信会让你在写业务时变得轻松

Android arch components 源码分析—— LiveData

ViewModel 中的 LiveData 类型不匹配