Пол свойства lateinit не был инициализирован

Использование привязки данных, ViewModel, LiveData (MVVM). В моем макете есть форма для добавления сведений о сотруднике.

макет:

<layout 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">
<data>
    <variable
        name = "viewModelAddEmployee"
        type = "com.app.roomemployeedemo.viewmodel.AddEmployeeViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
    android:id = "@+id/edt_lastname"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = ".activity.AddEmployeeActivity">
    <ScrollView
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:fillViewport = "true">
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width = "match_parent"
            android:layout_height = "match_parent">
            <EditText
                android:text = "@{viewModelAddEmployee.firstname}"
                android:id = "@+id/edt_firstname"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_marginTop = "40dp"
                android:ems = "10"
                android:hint = "Jaimin"
                android:inputType = "textPersonName"
                android:maxLength = "30"
                android:maxLines = "1"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toTopOf = "parent" />
            <EditText
                android:text = "@{viewModelAddEmployee.lastname}"
                android:id = "@+id/tv_lastname"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_marginTop = "20dp"
                android:ems = "10"
                android:hint = "Modi"
                android:inputType = "textPersonName"
                android:maxLength = "30"
                android:maxLines = "1"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toBottomOf = "@+id/edt_firstname" />
            <EditText
                android:text = "@{viewModelAddEmployee.age}"
                android:id = "@+id/edt_age"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_marginTop = "20dp"
                android:ems = "10"
                android:hint = "25"
                android:inputType = "textPersonName"
                android:maxLength = "3"
                android:maxLines = "1"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toBottomOf = "@+id/tv_lastname" />
            <EditText
                android:text = "@{viewModelAddEmployee.gender}"
                android:id = "@+id/edt_gender"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_marginTop = "20dp"
                android:ems = "10"
                android:hint = "Gender (M/F, m/f)"
                android:inputType = "textPersonName"
                android:maxLength = "1"
                android:maxLines = "1"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toBottomOf = "@+id/edt_age" />
            <EditText
                android:text = "@{viewModelAddEmployee.salary}"
                android:id = "@+id/edt_salary"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_marginTop = "20dp"
                android:ems = "10"
                android:hint = "Salary (50000)"
                android:inputType = "textPersonName"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toBottomOf = "@+id/edt_gender" />
            <Button
                android:onClick = "@{(v) -> viewModelAddEmployee.onAddEmployeeClick(v)}"
                android:id = "@+id/button"
                android:layout_width = "0dp"
                android:layout_height = "wrap_content"
                android:layout_marginStart = "40dp"
                android:layout_marginTop = "40dp"
                android:layout_marginEnd = "40dp"
                android:text = "ADD NOW"
                app:layout_constraintEnd_toEndOf = "parent"
                app:layout_constraintHorizontal_bias = "0.5"
                app:layout_constraintStart_toStartOf = "parent"
                app:layout_constraintTop_toBottomOf = "@+id/edt_salary" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

Ниже приведен класс ViewModel для того же:

 class AddEmployeeViewModel(mContext: Context) : ViewModel(){
    var mContext=mContext
    lateinit var firstname:MutableLiveData<String>
    lateinit var lastname:MutableLiveData<String>
    lateinit var age:MutableLiveData<Int>
    lateinit var gender:MutableLiveData<Char>
    lateinit var salary:MutableLiveData<Int>
    lateinit var repositoryEmployee:EmployeeRepository
    init{
        repositoryEmployee= EmployeeRepository(mContext)
    }
    fun onAddEmployeeClick(view: View)
    {
        repositoryEmployee.onAddEmployeeClick(mContext,firstname,lastname,age,gender,salary)
    }
}

Инициализированная Viewmodel и утилита привязки в классе Activity, как показано ниже:

class AddEmployeeActivity : AppCompatActivity() {
lateinit var viewModelAddEmployee: AddEmployeeViewModel
lateinit var binding: ActivityAddEmployeeBinding
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewModelAddEmployee = ViewModelProvider(this,AddEmployeeFactory(this@AddEmployeeActivity)).get(AddEmployeeViewModel::class.java)
    binding = DataBindingUtil.setContentView(
        this@AddEmployeeActivity,
        R.layout.activity_add_employee
    )
    binding?.setLifecycleOwner(this)
    binding?.viewModelAddEmployee = viewModelAddEmployee
}

}

Но, попадая ниже ошибки:

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property gender has not been initialized
            at com.app.roomemployeedemo.viewmodel.AddEmployeeViewModel.getGender(AddEmployeeViewModel.kt:16)

В чем может быть проблема? Особенно с Чар типом пола!!

0
0
466
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы объявляете свои живые объекты данных как lateinit var, что означает, что вы должны инициализировать их позже, прежде чем ссылаться на них. Вам нужно удалить lateinit и инициализировать при создании ViewModel или инициализировать каждое поле оперативных данных в вашем блоке init, как здесь:

firstname = MutableLiveData<>()

Что вы можете сделать, это

fun returnName(): LiveData<String> {
        if (firstname == null) {
            firstname = MutableLiveData()
            //call some function to set value to the variable
        }
        return firstname
    }

Это гарантирует, что вы не создадите несколько экземпляров этого списка, и он будет возвращать один и тот же экземпляр каждый раз. Вы можете реализовать его для любой переменной, которую хотите

Ответ принят как подходящий

В kotlin вы должны инициализировать свойство lateinit. Добавьте строку ниже в oncreate -

 gender = MutableLiveData<Char>()

Как я могу присвоить значение или сказать значение String при его объявлении и удалении латентности?

Jaimin Modi 23.12.2020 10:41

Вы можете просто удалить lateinit из объявления и присвоить значение переменной, например var value = "Hello"

Priyanka 23.12.2020 10:48

Ожидается получение или установка свойства Showing Property!

Jaimin Modi 23.12.2020 11:12

var имя:MutableLiveData<String> = ""

Jaimin Modi 23.12.2020 11:18

Вы не указываете необходимые данные. Используйте var firstname: MutableLiveData<String> = MutableLiveData<String>()

Priyanka 23.12.2020 11:30

Получение: вызвано: android.content.res.Resources$NotFoundException: идентификатор строкового ресурса #0x0 в android.content.res.Resources.getText(Resources.java:339) в android.widget.TextView.setText(TextView.java: 5496) в com.app.roomemployeedemo.databinding.ActivityAddEmployeeBind‌​ingImpl.executeBindi‌​ngs(ActivityAddEmplo‌​yeeBindingImpl.java:‌​272)

Jaimin Modi 23.12.2020 13:55

Обычно свойства, объявленные как имеющие ненулевой тип, должны быть инициализированы в конструкторе. Однако довольно часто это не удобно. Например, свойства можно инициализировать с помощью внедрения зависимостей или в методе настройки модульного теста. В этом случае вы не можете указать ненулевой инициализатор в конструкторе, но вы все же хотите избежать проверки нулей при ссылке на свойство внутри тела класса.

Чтобы справиться с этим случаем, вы можете пометить свойство модификатором lateinit:

Образец

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // dereference directly
    }
}

В вашем случае значения должны быть загружены в переменные во ViewModel.

В вашем случае;

class AddEmployeeViewModel(mContext: Context) : ViewModel(){
    var mContext=mContext
    lateinit var firstname:MutableLiveData<String>
    lateinit var lastname:MutableLiveData<String>
    lateinit var age:MutableLiveData<Int>
    lateinit var gender:MutableLiveData<Char>
    lateinit var salary:MutableLiveData<Int>
    lateinit var repositoryEmployee:EmployeeRepository
        init{
              repositoryEmployee= EmployeeRepository(mContext)
              lastname = MutableLiveData<String>()
              firstname = MutableLiveData<String>()
              age = MutableLiveData<Int>()
              gender = MutableLiveData<Char>()
              salary = MutableLiveData<Int>()
        }
fun onAddEmployeeClick(view: View)
    {
        repositoryEmployee.onAddEmployeeClick(mContext,firstname,lastname,age,gender,salary)
    }
}

Лучшая практика

private val _sampleVar = MutableLiveData<String>()
val sampleVar: LiveData<String>
   get() = _sampleVar

Как я могу присвоить значение или сказать значение String при его объявлении и удалении латентности? – вместо того, чтобы делать age=MutableLiveData<Int>() ?

Jaimin Modi 23.12.2020 10:42

Другие вопросы по теме