Tengo un EditText y estoy configurando un error o descarto el error después de que cambia el texto. Sin embargo, de alguna manera obtengo NPE cuando intento acceder a EditText desde el método afterTextChanged() .
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" } })No se reproduce constantemente, pero durante el último mes hubo docenas de fallas en diferentes dispositivos desde Android 4.4.2 hasta 6.0.1.
¿Cómo puede suceder eso? Si se destruye Fragment , no se debería llamar a TextWatcher , ¿verdad? ¿Cómo puede ser prevenido?
¿Cómo puede suceder eso?
Lo más probable es que, cuando esto suceda, su aplicación pase a primer plano mientras el usuario está escribiendo (por ejemplo, debido a una llamada entrante).
Si se destruye
Fragment, no se debería llamar aTextWatcher, ¿verdad?
Derecha. Pero te estás perdiendo el orden en que Fragment y Layout inflados "dentro" se destruyen. La destrucción de esos dos no se realiza simultáneamente: el Layout se destruye primero.
Como puede ver, TextWatcher es una instancia de clase interna anónima que mantiene una referencia a su clase externa , su Fragment , que se destruirá en último lugar. El punto clave aquí es que cualquier cambio de texto dentro de EditText que provenga de TextWatcher se realice de forma asíncrona: la vista de proceso de su aplicación recibe "notificaciones" de otro proceso en el sistema, aplicación de teclado virtual ( la predeterminada ).
En caso de que dicha "notificación" llegue en un momento en que su EditText haya sido destruido pero su Fragment no, obtendrá NPE .
¿Cómo puede ser prevenido?
Simplemente use phone_number_input?.error = ...