如何使用 RxTextView (RxBinding) 检测 EditText 何时为空

How to detect when an EditText is empty using RxTextView (RxBinding)

我正在 EditText 上进行验证。如果 CharSequence 为空或不以 "https://" 开头,我希望它无效。我也在使用 RxBinding,特别是 RxTextView。问题是,当只剩下一个字符时,我将其删除,在 CharSequence 中没有留下任何字符,地图运算符不会触发发射。换句话说,当 EditText 为空时,我希望我的地图运算符 return false。我开始认为这可能无法按照我的方式进行。有什么替代方案?

这是我的 Observable / Disposable:

val systemIdDisposable = RxTextView.textChanges(binding.etSystemId)
            .skipInitialValue()
            .map { charSeq ->
                if (charSeq.isEmpty()) {
                    false
                } else {
                    viewModel.isSystemIdValid(charSeq.toString())
                }
            }
            .subscribe { isValid ->
                if (!isValid) {
                    binding.systemIdTextInputLayout.isErrorEnabled = true
                    binding.systemIdTextInputLayout.error = viewModel.authErrorFields.value?.systemId
                } else {
                    binding.systemIdTextInputLayout.isErrorEnabled = false
                    binding.systemIdTextInputLayout.error = viewModel.authErrorFields.value?.systemId
                }
            }

这是我的 ViewModel 中的一个函数,我将 CharSequence 传递给它进行验证:

fun isSystemIdValid(systemId: String?): Boolean {

    return if (systemId != null && systemId.isNotEmpty()) {
        _authErrors.value?.systemId = null 
        true
    } else {
        _authErrors.value?.systemId =
            getApplication<Application>().resources.getString(R.string.field_empty_error)
        false
    }
}

在上面睡了一觉之后,我想通了。

我把RxTextView.textChanges改成了RxTextView.textChangeEvents。这允许我查询 CharSequence 的文本值(使用 textChangeEvents 提供的 text() 方法),即使它是空的。由于其他一些变化(与我在这个问题中提出的问题并不真正相关),我也能够减少一些条件代码。我只是把它放在那里,以防有人遇到这个并对这些变化感到好奇。要点是您可以使用 RxTextView.textChangeEvents.

获得空排放

这是我的新观察者:

 val systemIdDisposable = RxTextView.textChangeEvents(binding.etSystemId)
            .skipInitialValue()
            .map { charSeq -> viewModel.isSystemIdValid(charSeq.text().toString()) }
            .subscribe {
                binding.systemIdTextInputLayout.error = viewModel.authErrors.value?.systemId
            }

这是我来自 ViewModel 的验证代码:

fun isSystemIdValid(systemId: String?): Boolean {

        val auth = _authErrors.value

        return if (systemId != null && systemId.isNotEmpty()) {
            auth?.systemId = null
            _authErrors.value = auth
            true
        } else {
            auth?.systemId =
                getApplication<Application>().resources.getString(R.string.field_empty_error)
            _authErrors.value = auth
            false
        }
    }

最后,如果有人对我如何使用我的 LiveData / MutableLiveData 对象感到好奇;我创建了一个私有的 MutableLiveData 对象,并且只公开了一个 returns 第一个对象的值的不可变 LiveData 对象。我这样做是为了更好的封装/数据隐藏。这是一个例子:

private val _authErrors: MutableLiveData<AuthErrorFields> by lazy {
        MutableLiveData<AuthErrorFields>()
    }
    val authErrors: LiveData<AuthErrorFields>
        get() { return _authErrors }

希望这对某人有所帮助!