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.

中的输入

我想实现以下目标:

  1. 使用双向数据绑定
  2. 在用户输入任何内容之前,不应显示任何错误。
  3. 当用户输入内容并删除它们时,应显示一条错误消息 Input cannot be empty
  4. 当用户点击 Reset 时,EditText 中的输入应该被清除。
  5. 当用户单击 Reset 时,应该不会显示错误

我是怎么做到的

布局xml:(为简单起见,我在这里只显示EditTextTextView。您可以转到示例项目以获得完整版本)

        <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时显示错误

更多观察

  1. 通过调试,我可以观察到在onReset()之后调用了userInput.value = ""。可能是数据绑定库?这也应该是整个问题的原因。

  2. 如果我在输入已经为空的情况下点击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
    }
}