Kotlin:EditText 在 afterTextChanged() 中为空

Posted

技术标签:

【中文标题】Kotlin:EditText 在 afterTextChanged() 中为空【英文标题】:Kotlin: EditText is null in afterTextChanged() 【发布时间】:2019-07-22 10:20:07 【问题描述】:

我有一个EditText,我在其中设置了一个错误,或者在文本更改后消除该错误。但是,当我尝试从afterTextChanged() 方法访问EditText 时,不知何故我得到了NPE

phone_number_input.addTextChangedListener(object : TextWatcher() 
        ...
        override fun afterTextChanged(s: Editable?) 
            if (isValid(s.toString()) 
                phone_number_input.error = null // <-- NPE happens here
            else
                phone_number_input.error = "Number is invalid"
        
    )

它不是不断重现,但在上个月,从 android 4.4.2 到 6.0.1 的不同设备上发生了数十次崩溃。

怎么会这样?如果Fragment 被销毁,则不应调用TextWatcher,对吗?如何预防?

【问题讨论】:

尝试添加this@Activity/Fragment.phone_number_input... 【参考方案1】:

怎么会这样?

最有可能发生这种情况时,您的应用会在用户输入时进入前台(例如,由于来电)。

如果Fragment被销毁,TextWatcher不应该被调用,对吧?

没错。但是你错过了FragmentLayout 在“内部”膨胀它被摧毁的顺序。这两者的销毁不会同时进行 - Layout 首先被销毁。

如您所见,TextWatcher 是anonymous inner class instance that keeps reference to its outer class,您的Fragment,将在最后被销毁。这里的关键点是,EditText 中来自TextWatcher 的任何文本更改都是异步完成的——您的应用程序的进程视图从系统中的另一个进程、软键盘应用程序 (default one) 获取“通知”。

如果您的EditText 已被销毁但您的Fragment 未销毁时出现这样的“通知”,您将获得NPE

如何预防?

只需使用phone_number_input?.error = ...

【讨论】:

感谢您的回答,请注意,在可空类型上使用 s.toString 是可以的,因为 kotlin 具有该 public fun Any?.toString(): String 的扩展名,它会返回 "null" 以防 @987654338 @是null

以上是关于Kotlin:EditText 在 afterTextChanged() 中为空的主要内容,如果未能解决你的问题,请参考以下文章

在 EditText Kotlin 中设置文本

Kotlin - DialogFragment中Edittext中的字符串不保存在数据类中

kotlin.NotImplementedError: 操作未在 EditText 上使用 addTextChangedListenerher 实现

尝试从 Kotlin 中的另一个活动访问 EditText 时出现空指针异常

Kotlin优雅地判断EditText数据是否为空

Kotlin优雅地判断EditText数据是否为空