lateinit 属性 性别尚未初始化
lateinit property gender has not been initialized
使用数据绑定、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:
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)
}
}
已在 Activity class 中初始化视图模型和绑定实用程序,如下所示:
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)
可能是什么问题?尤其是 Char 类型的性别!!
您将实时数据对象声明为 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
}
这将确保您不会创建该列表的多个实例,并且它会 return 每次都创建相同的实例。
你可以在任何你想要的变量上实现它
在 kotlin 中,您必须初始化 lateinit 属性。将以下行添加到 oncreate -
gender = MutableLiveData<Char>()
通常,声明为具有非空类型的属性必须在构造函数中初始化。然而,这通常并不方便。例如,可以通过依赖注入或单元测试的设置方法来初始化属性。在这种情况下,您不能在构造函数中提供非空初始化程序,但在引用 class.
主体内的 属性 时,您仍然希望避免空检查
要处理这种情况,您可以使用 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
使用数据绑定、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:
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)
}
}
已在 Activity class 中初始化视图模型和绑定实用程序,如下所示:
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)
可能是什么问题?尤其是 Char 类型的性别!!
您将实时数据对象声明为 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
}
这将确保您不会创建该列表的多个实例,并且它会 return 每次都创建相同的实例。 你可以在任何你想要的变量上实现它
在 kotlin 中,您必须初始化 lateinit 属性。将以下行添加到 oncreate -
gender = MutableLiveData<Char>()
通常,声明为具有非空类型的属性必须在构造函数中初始化。然而,这通常并不方便。例如,可以通过依赖注入或单元测试的设置方法来初始化属性。在这种情况下,您不能在构造函数中提供非空初始化程序,但在引用 class.
主体内的 属性 时,您仍然希望避免空检查要处理这种情况,您可以使用 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