Data Binding EditText set null 被 set empty String 替换
Data Binding EditText set null was replaced by set empty String
我创建了一个 sample project 可以重现这个问题。
预期行为
我有一个EditText
。我有一个 TextView
,它显示了这个 EditText
中输入的错误。我还有一个重置按钮,可以重置 EditText
.
中的输入
我想实现以下目标:
- 使用双向数据绑定
- 在用户输入任何内容之前,不应显示任何错误。
- 当用户输入内容并删除它们时,应显示一条错误消息
Input cannot be empty
。
- 当用户点击
Reset
时,EditText
中的输入应该被清除。
- 当用户单击
Reset
时,应该不会显示错误。
我是怎么做到的
布局xml:(为简单起见,我在这里只显示EditText
和TextView
。您可以转到示例项目以获得完整版本)
<EditText
android:id="@+id/et"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_width="0dp"
android:text="@={vm.userInput}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvError"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintTop_toBottomOf="@id/et"
app:layout_constraintStart_toStartOf="@id/et"
app:layout_constraintEnd_toEndOf="@id/et"
tools:text="I am some error"
android:text="@{vm.errorText}"
android:textColor="@android:color/holo_red_dark"
android:visibility="@{vm.isErrorVisible() ? View.VISIBLE : View.GONE}" />
视图模型:
val userInput = MutableLiveData<String?>(null)
val errorText = userInput.map { input ->
if (input?.isBlank() == true) {
"This field cannot be empty"
} else {
""
}
}
val isErrorVisible = errorText.map { errorText.value?.isNotBlank() == true }
fun onReset() {
userInput.value = null
}
观察到的行为
1、2、3达成。 4无法实现-点击Reset
时显示错误
更多观察
通过调试,我可以观察到在onReset()
之后调用了userInput.value = ""
。可能是数据绑定库?这也应该是整个问题的原因。
如果我在输入已经为空的情况下点击reset()
,则不会显示错误。即,如果输入为空,则不会发生上述第 1 点。
问题
我怎样才能达到4?
单击重置按钮时,errorText
地图功能被执行两次 - 立即从 onReset()
中的更改开始,我相信,当 TextView 值已更新。
除了重新考虑整体设计之外,我建议您使用空值和编辑标志来确定 userInput
为何为空。类似于以下内容:
class MainViewModel : ViewModel() {
private var isInReset = false
val userInput = MutableLiveData<String?>(null)
val errorText = userInput.map { input ->
// We only care to have an opinion if the input field is not null and blank.
// Here we determine why it is blank. Is it because it was reset (OK) or because
// the user deleted all text (not OK).
if (input == null || input.isNotBlank()) {
""
} else if (isInReset) {
isInReset = false
""
} else {
"This field cannot be empty"
}
}
val isErrorVisible = errorText.map { errorText.value?.isNotBlank() == true }
fun onReset() {
isInReset = true
userInput.value = null
}
}
我创建了一个 sample project 可以重现这个问题。
预期行为
我有一个EditText
。我有一个 TextView
,它显示了这个 EditText
中输入的错误。我还有一个重置按钮,可以重置 EditText
.
我想实现以下目标:
- 使用双向数据绑定
- 在用户输入任何内容之前,不应显示任何错误。
- 当用户输入内容并删除它们时,应显示一条错误消息
Input cannot be empty
。 - 当用户点击
Reset
时,EditText
中的输入应该被清除。 - 当用户单击
Reset
时,应该不会显示错误。
我是怎么做到的
布局xml:(为简单起见,我在这里只显示EditText
和TextView
。您可以转到示例项目以获得完整版本)
<EditText
android:id="@+id/et"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_width="0dp"
android:text="@={vm.userInput}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvError"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintTop_toBottomOf="@id/et"
app:layout_constraintStart_toStartOf="@id/et"
app:layout_constraintEnd_toEndOf="@id/et"
tools:text="I am some error"
android:text="@{vm.errorText}"
android:textColor="@android:color/holo_red_dark"
android:visibility="@{vm.isErrorVisible() ? View.VISIBLE : View.GONE}" />
视图模型:
val userInput = MutableLiveData<String?>(null)
val errorText = userInput.map { input ->
if (input?.isBlank() == true) {
"This field cannot be empty"
} else {
""
}
}
val isErrorVisible = errorText.map { errorText.value?.isNotBlank() == true }
fun onReset() {
userInput.value = null
}
观察到的行为
1、2、3达成。 4无法实现-点击Reset
时显示错误
更多观察
通过调试,我可以观察到在
onReset()
之后调用了userInput.value = ""
。可能是数据绑定库?这也应该是整个问题的原因。如果我在输入已经为空的情况下点击
reset()
,则不会显示错误。即,如果输入为空,则不会发生上述第 1 点。
问题
我怎样才能达到4?
单击重置按钮时,errorText
地图功能被执行两次 - 立即从 onReset()
中的更改开始,我相信,当 TextView 值已更新。
除了重新考虑整体设计之外,我建议您使用空值和编辑标志来确定 userInput
为何为空。类似于以下内容:
class MainViewModel : ViewModel() {
private var isInReset = false
val userInput = MutableLiveData<String?>(null)
val errorText = userInput.map { input ->
// We only care to have an opinion if the input field is not null and blank.
// Here we determine why it is blank. Is it because it was reset (OK) or because
// the user deleted all text (not OK).
if (input == null || input.isNotBlank()) {
""
} else if (isInReset) {
isInReset = false
""
} else {
"This field cannot be empty"
}
}
val isErrorVisible = errorText.map { errorText.value?.isNotBlank() == true }
fun onReset() {
isInReset = true
userInput.value = null
}
}