Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Qué está desencadenando esta instancia de excepción: "java.lang.IllegalArgumentException: El observador es nulo." Y cómo podría evitarse?

Estoy recibiendo esta excepción al regresar a ListActivity original después de abrir una nueva actividad con el contenido del elemento seleccionado por el usuario. Sólo ocurre en Ice Cream Sandwich.

Este es el rastro:

  java.lang.IllegalArgumentException: The observer is null. at android.database.Observable.unregisterObserver(Observable.java:59) at android.widget.BaseAdapter.unregisterDataSetObserver(BaseAdapter.java:42) at android.widget.AbsListView.onDetachedFromWindow(AbsListView.java:2373) at android.view.View.dispatchDetachedFromWindow(View.java:9756) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2274) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2272) at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.java:2227) at android.view.ViewRootImpl.doDie(ViewRootImpl.java:3679) at android.view.ViewRootImpl.die(ViewRootImpl.java:3667) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:320) at android.view.WindowManagerImpl$CompatModeWrapper.removeViewImmediate(WindowManagerImpl.java:139) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3144) at android.app.ActivityThread.access$1200(ActivityThread.java:122) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1179) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4340) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method) 

Ninguno de mi código se menciona en la pila por lo que es realmente desconcertante y no puedo hacer un evento sucio catch: /

Estoy registrando un DataSetObserver anónimo sólo cuando se crea la actividad. Además, la actividad está incrustada dentro de un ActivityGroup (que está obsoleto en 4.0 pero debería soportarlo, esperaba).

¿Alguien ha tenido este problema con el nuevo sistema operativo?

Gracias por adelantado.


Actualizar:

Ok, creo que encontré el origen del problema, aunque no estoy seguro de cómo resolverlo.

Dentro de AbsListView.onDetachedFromWindow() Tenemos esto:

 if (mAdapter != null) { // Android code added on ICS mAdapter.unregisterDataSetObserver(mDataSetObserver); mDataSetObserver = null; } 

Que, una vez que el observador no está registrado, se anula. El problema viene que, por alguna razón, en ICS se llama dos veces. Creo que es un poco tonto para comprobar los parámetros nulos dentro de una operación de eliminación como lo hacen en la clase Observable :

 public void unregisterObserver(T observer) { // Android code if (observer == null) { throw new IllegalArgumentException("The observer is null."); } synchronized(mObservers) { int index = mObservers.indexOf(observer); if (index == -1) { throw new IllegalStateException("Observer " + observer + " was not registered."); } mObservers.remove(index); } } 

¿Por qué no lo ignoran? ¬¬ Podrían hacer esto y funcionaría bien (o mejor):

 public void unregisterObserver(T observer) { // Android code synchronized(mObservers) { mObservers.remove(observer); } } 

2 Solutions collect form web for “¿Qué está desencadenando esta instancia de excepción: "java.lang.IllegalArgumentException: El observador es nulo." Y cómo podría evitarse?”

Este problema se introdujo en Android 4.0.3, y la clase Observable se cambió para lanzar una excepción cuando un observador fue liberado más de una vez. Se ha notificado como un error y se puede leer aquí: http://code.google.com/p/android/issues/detail?id=22946 .

La forma más sencilla de evitar este problema consiste en ajustar el adaptador subyacente y evitar varias versiones.

 @Override public void unregisterDataSetObserver(DataSetObserver observer) { if (observer != null) { super.unregisterDataSetObserver(observer); } } 

Pero eso no funcionará en todos los casos, por ejemplo, ExpandableListView tiene un adaptador interno al que no se puede acceder. Una solución alternativa aquí es envolver el ExpandableListView y capturar la excepción. Esta solución funcionó para mí, y todavía no he encontrado ningún efecto secundario.

 public class PatchedExpandableListView extends ExpandableListView { public PatchedExpandableListView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDetachedFromWindow() { try { super.onDetachedFromWindow(); } catch(IllegalArgumentException iae) { // Workaround for http://code.google.com/p/android/issues/detail?id=22751 } } } 

Cometí el tonto error de pensar que ninguna de mis clases se mencionó en la traza, pero LoadingDataView es una de ellas. No se muestra en el rastro original sino en otro que estaba relacionado.

Dentro de esa clase hay un ArrayAdapter anónimo que fue donde el incidente está sucediendo, así que añadí esto como un trabajo alrededor:

 @Override public void unregisterDataSetObserver(DataSetObserver observer) { if (observer != null) { super.unregisterDataSetObserver(observer); } } 

Y parece que funciona ahora, aunque todavía no estoy seguro de por qué este método se llamó dos veces.

Aunque, por ahora voy a usar Fragmentos tanto como pueda;)

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.