textwatchcher为我的EditText是触发后textchanged多次



我使用的是EditText,我想要预设文本或让用户键入一些东西。我想把它改成"all-caps">所以我为TextWatcher实现了大写函数。

您可以使用此EditTextTextWatcher多次进入和离开屏幕来回切换屏幕-这意味着我必须在屏幕进入/离开事件时从EditText正确注册和取消注册TextWatcher

我注意到的是,如果我连续多次进入和离开屏幕,在第5次进入时,我的整个应用程序被冻结-所以有些东西阻塞了UI线程。

经过更深入的调查,我发现如果我调用editText.setText("some string"),它将多次触发我的afterTextChanged侦听器。在第5次输入时,它像一样在一行中触发了50次导致UI线程阻塞。

这是如何修复或它是Android方面的bug ?

代码:输入时初始化屏幕:

initEditTextListener()
App.log("FormScreen - setData")
formFirstEt?.setText(item.name)
private var inputWatcher: TextWatcher? = null
private fun initEditTextListener(){
        formFirstEt?.onEditorAction{
            formInputValidation(this.text.toString(), formFirstEt, App.getString("form_empty"), App.getString("form_empty_reason"))
            validateData()
            formSecondEt?.let { s -> if (s.isEnabled) s.requestFocus() }
        }
        inputWatcher = object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                App.log("FormScreen - initEditTextListener - afterTextChanged")
                validateData()
            }
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                App.log("FormScreen - initEditTextListener - onTextChanged")
                validateData()
                formFirstEt?.let { et -> onFormFirstInputChanged(s.toString(), this, et)}
            }
        }
        inputWatcher?.let {formFirstEt?.addTextChangedListener(it)}
    }

全大写转换函数(不应该触发texttwatcher)

fun onFormFirstInputChanged(s: String, tv: TextWatcher, et: EditText) {
    et.removeTextChangedListener(tv)
    if (isFirstInputValid(s)) {
        with(et) {
            text.clear()
            append(s.toUpperCase(Locale.getDefault()))
            setSelection(s.length)
        }
    } else {
        val substring = s.substring(0, s.length - 1)
        with(et) {
            text.clear()
            append(substring.toUpperCase(Locale.getDefault()))
            setSelection(substring.length)
        }
    }
    et.addTextChangedListener(tv)
}

离开前清理屏幕:

formFirstEt?.setText("")
inputWatcher?.let { formFirstEt?.removeTextChangedListener(it) }
inputWatcher = null

日志:

-- First time screen enter ---
2021-01-14 11:24:50.324 1136-1136/? I/Project: FormScreen - setData
2021-01-14 11:24:50.458 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:50.460 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:52.838 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:52.841 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
-- Second time screen enter --
2021-01-14 11:24:56.324 1136-1136/? I/Project: FormScreen - setData
2021-01-14 11:24:56.366 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.367 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.368 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:56.368 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.369 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:56.369 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.370 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.370 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:56.371 1136-1136/? I/Project: FormScreen - initEditTextListener - onTextChanged
2021-01-14 11:24:56.372 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:56.372 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged
2021-01-14 11:24:56.373 1136-1136/? I/Project: FormScreen - initEditTextListener - afterTextChanged

更新:这是Kotlin的一些行为。问题是formFirstEt?.setText(""),我希望它会添加空字符串EditText,但显然它是添加字符终止符。Kotlin不能识别它的String,而是默认的char array,末尾有字符。这个字符数组在本地setText函数中触发了一些奇怪的行为,这是垃圾邮件afterTextChanged

修复:

//type declaration String is important without it it will not work
val emptyString: String = ""
formFirstEt?.setText(emptyString)

同样的问题。我有一个DialogFragment,我使用TextInputEditText与观察者。如果在onCreateView中输入addTextChangedListener(在使用DialogFragment时普遍期望),则侦听器每次击键触发一次或多次(随机)。

即使使用局部变量watcherEnabled来确保格式化输入的值不会重新触发监视器也会失败。

尝试将监视器的分配移到onResume。这感觉非常荒谬和错误,但似乎已经解决了问题。

还要注意,文本监视程序似乎只有在使用计算机键盘向模拟器输入文本时才会触发多次。当我使用模拟器的键盘时,监视器似乎没有失火。这可能表明该错误仅与模拟器有关。

相关内容

  • 没有找到相关文章

最新更新