为什么我的 data-binding with EditText 不起作用?
Why does my data-binding with EditText not work?
我有这个 class 用于房间:
data class Piece(
@ColumnInfo(name = "title")
var title: String
)
然后我有一个表单 class,它只包含我想在 EditText
中显示的字符串值。
class CreateEditPieceForm {
var title: String = ""
}
我的 ViewModel 包含这些 classes:
的实例
class EditPieceViewModel(...) : AndroidViewModel(application) {
val piece : LiveData<Piece?> = database.getMyPiece() // valid Piece with title set
val form = CreateEditPieceForm()
}
在我的片段中,我观察了片段:
viewModel.piece.observe(this, Observer {piece ->
piece?.let {
viewModel.updateInputValues(piece)
}
})
ViewModel 中的 updateInputValues 函数简单地设置以下形式的值:
fun updateInputValues(piece: Piece) {
Log.d("mylog", "value: " + piece.title) // logs correct value
form.title = piece.title // setting this does not change EditText
}
最后,在我的布局中,我尝试使用数据绑定在 EditText 中显示来自 form.title 的文本:
<data>
<variable
name="viewModel"
type="com.example.tutorial.createedit.CreateEditPieceViewModel" />
</data>
<!-- ... -->
<EditText
android:id="@+id/input_title"
<!-- ... -->
android:inputType="text"
android:text="@={viewModel.form.title}" />
当我用这个片段打开屏幕时,EditText 是空的。我知道对片段标题的查询是正确的,因为我在设置 EditText 的文本属性之前记录了它。
当我在空白字段中键入内容时,viewModel.form.title
的值被设置为该值。
为什么一开始没有设置正确?
Databinding 不要与
View binding.
如指南中所述,让 EditPieceViewModel 实现 Observable 并使 form.title
@Bindable。
现在可以了。我仍然不完全理解数据绑定库,所以欢迎任何改进代码的建议!
我更改了我的 ViewModel 以实现 Observable 并向其添加了一些方法:
// Make sure to import the correct Observable interface
import androidx.databinding.Observable
// ...
class EditPieceViewModel(...) : AndroidViewModel(application), Observable {
// ...
// New getter and setter methods for my title field:
@Bindable
fun getTitle() : String {
return form.title
}
fun setTitle(value: String) {
if(form.title != value) {
form.title = value
notifyPropertyChanged(BR.title) // This line is important for EditText' value to update
}
}
// New methods added for Observable:
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes should be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
在布局 xml 中,我将标题更改为观察 viewModel.title 而不是 viewModel.form.title:
<EditText
// ...
android:text="@={viewModel.title}" />
最后在 updateInputValues 中我调用我的自定义 setter:
fun updateInputValues(piece: Piece) {
setTitle(piece.title)
}
我有这个 class 用于房间:
data class Piece(
@ColumnInfo(name = "title")
var title: String
)
然后我有一个表单 class,它只包含我想在 EditText
中显示的字符串值。
class CreateEditPieceForm {
var title: String = ""
}
我的 ViewModel 包含这些 classes:
的实例class EditPieceViewModel(...) : AndroidViewModel(application) {
val piece : LiveData<Piece?> = database.getMyPiece() // valid Piece with title set
val form = CreateEditPieceForm()
}
在我的片段中,我观察了片段:
viewModel.piece.observe(this, Observer {piece ->
piece?.let {
viewModel.updateInputValues(piece)
}
})
ViewModel 中的 updateInputValues 函数简单地设置以下形式的值:
fun updateInputValues(piece: Piece) {
Log.d("mylog", "value: " + piece.title) // logs correct value
form.title = piece.title // setting this does not change EditText
}
最后,在我的布局中,我尝试使用数据绑定在 EditText 中显示来自 form.title 的文本:
<data>
<variable
name="viewModel"
type="com.example.tutorial.createedit.CreateEditPieceViewModel" />
</data>
<!-- ... -->
<EditText
android:id="@+id/input_title"
<!-- ... -->
android:inputType="text"
android:text="@={viewModel.form.title}" />
当我用这个片段打开屏幕时,EditText 是空的。我知道对片段标题的查询是正确的,因为我在设置 EditText 的文本属性之前记录了它。
当我在空白字段中键入内容时,viewModel.form.title
的值被设置为该值。
为什么一开始没有设置正确?
Databinding 不要与 View binding.
如指南中所述,让 EditPieceViewModel 实现 Observable 并使 form.title
@Bindable。
现在可以了。我仍然不完全理解数据绑定库,所以欢迎任何改进代码的建议!
我更改了我的 ViewModel 以实现 Observable 并向其添加了一些方法:
// Make sure to import the correct Observable interface
import androidx.databinding.Observable
// ...
class EditPieceViewModel(...) : AndroidViewModel(application), Observable {
// ...
// New getter and setter methods for my title field:
@Bindable
fun getTitle() : String {
return form.title
}
fun setTitle(value: String) {
if(form.title != value) {
form.title = value
notifyPropertyChanged(BR.title) // This line is important for EditText' value to update
}
}
// New methods added for Observable:
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes should be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
在布局 xml 中,我将标题更改为观察 viewModel.title 而不是 viewModel.form.title:
<EditText
// ...
android:text="@={viewModel.title}" />
最后在 updateInputValues 中我调用我的自定义 setter:
fun updateInputValues(piece: Piece) {
setTitle(piece.title)
}