首页 > 解决方案 > 如何使用 RxTextView (RxBinding) 检测 EditText 何时为空

问题描述

我正在对EditText. CharSequence如果它为空或不以"https://"开头,我希望它无效。我也在使用RxBinding,特别是RxTextView. 问题是,当剩下一个字符时,然后我将其删除,在地图运算符中没有留下任何字符时CharSequence不会触发发射。换句话说,我希望我的地图运算符在 EditText 为空时返回 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
    }
}

标签: androidkotlinrx-binding

解决方案


睡了之后,我就明白了。

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

Lastly, if anyone is curious about how I'm using my LiveData / MutableLiveData objects; I create a private MutableLiveData object and only expose an immutable LiveData object that returns the values of the first object. I do this for better encapsulation / data hiding. Here is an example:

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

Hope this helps someone!


推荐阅读