Vista de Android no conectada al administrador de ventanas

Tengo algunas de las siguientes excepciones:

java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:191) at android.view.Window$LocalWindowManager.updateViewLayout(Window.java:428) at android.app.Dialog.onWindowAttributesChanged(Dialog.java:596) at android.view.Window.setDefaultWindowFormat(Window.java:1013) at com.android.internal.policy.impl.PhoneWindow.access$700(PhoneWindow.java:86) at com.android.internal.policy.impl.PhoneWindow$DecorView.drawableChanged(PhoneWindow.java:1951) at com.android.internal.policy.impl.PhoneWindow$DecorView.fitSystemWindows(PhoneWindow.java:1889) at android.view.ViewRoot.performTraversals(ViewRoot.java:727) at android.view.ViewRoot.handleMessage(ViewRoot.java:1633) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4338) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) at dalvik.system.NativeStart.main(Native Method) 

Lo busqué en Google y veo que tiene algo que ver con las ventanas emergentes y el giro de la pantalla, pero no hay ninguna referencia a mi código.

Las preguntas son:

  1. ¿Hay alguna manera de averiguar exactamente cuándo está sucediendo este problema?
  2. aparte de girar la pantalla, ¿hay otro evento o acción que desencadene este error?
  3. ¿Cómo evito que esto suceda?

Tuve este problema en el que en una orientación de pantalla cambio, la actividad finalizó antes de la AsyncTask con el diálogo de progreso completado. onPause() resolver esto al establecer el diálogo para onPause() y luego verificar esto en AsyncTask antes de descartar.

 @Override public void onPause() { super.onPause(); if ((mDialog != null) && mDialog.isShowing()) mDialog.dismiss(); mDialog = null; } 

… en mi AsyncTask:

 protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true); } protected void onPostExecute(Object result) { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } } 

Después de una pelea con este problema, finalmente termino con esta solución alternativa:

 /** * Dismiss {@link ProgressDialog} with check for nullability and SDK version * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissProgressDialog(ProgressDialog dialog) { if (dialog != null && dialog.isShowing()) { //get the Context object that was used to great the dialog Context context = ((ContextWrapper) dialog.getContext()).getBaseContext(); // if the Context used here was an activity AND it hasn't been finished or destroyed // then dismiss it if (context instanceof Activity) { // Api >=17 if (!((Activity) context).isFinishing() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (!((Activity) context).isDestroyed()) { dismissWithExceptionHandling(dialog); } } else { // Api < 17. Unfortunately cannot check for isDestroyed() dismissWithExceptionHandling(dialog); } } } else // if the Context used wasn't an Activity, then dismiss it too dismissWithExceptionHandling(dialog); } dialog = null; } } /** * Dismiss {@link ProgressDialog} with try catch * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissWithExceptionHandling(ProgressDialog dialog) { try { dialog.dismiss(); } catch (final IllegalArgumentException e) { // Do nothing. } catch (final Exception e) { // Do nothing. } finally { dialog = null; } } 

A veces, un buen manejo de excepciones funciona bien si no hay una mejor solución para este problema.

Agregué lo siguiente al manifiesto para esa actividad

 android:configChanges="keyboardHidden|orientation|screenLayout" 

Si tiene un objeto de Activity rondando, puede usar el método isDestroyed() :

 Activity activity; // ... if (!activity.isDestroyed()) { // ... } 

Esto es bueno si tiene una subclase AsyncTask no anónima que utiliza en varios lugares.

Estoy usando una clase estática personalizada que hace- muestra y oculta un diálogo. esta clase está siendo utilizada por otras actividades, no solo una actividad. Ahora el problema que describes también me pareció y me he quedado a dormir para encontrar una solución.

¡Finalmente te presento la solución!

si desea mostrar o descartar un diálogo y no sabe qué actividad inició el diálogo para tocarlo, entonces el siguiente código es para usted.

  static class CustomDialog{ public static void initDialog(){ ... //init code ... } public static void showDialog(){ ... //init code for show dialog ... } /****This is your Dismiss dialog code :D*******/ public static void dismissProgressDialog(Context context) { //Can't touch other View of other Activiy.. //http://stackoverflow.com/questions/23458162/dismiss-progress-dialog-in-another-activity-android if ( (progressdialog != null) && progressdialog.isShowing()) { //is it the same context from the caller ? Log.w("ProgressDIalog dismiss", "the dialog is from"+progressdialog.getContext()); Class caller_context= context.getClass(); Activity call_Act = (Activity)context; Class progress_context= progressdialog.getContext().getClass(); Boolean is_act= ( (progressdialog.getContext()) instanceof Activity )?true:false; Boolean is_ctw= ( (progressdialog.getContext()) instanceof ContextThemeWrapper )?true:false; if (is_ctw) { ContextThemeWrapper cthw=(ContextThemeWrapper) progressdialog.getContext(); Boolean is_same_acivity_with_Caller= ((Activity)(cthw).getBaseContext() == call_Act )?true:false; if (is_same_acivity_with_Caller){ progressdialog.dismiss(); progressdialog = null; } else { Log.e("ProgressDIalog dismiss", "the dialog is NOT from the same context! Can't touch.."+((Activity)(cthw).getBaseContext()).getClass()); progressdialog = null; } } } } } 

Para la pregunta 1):

Teniendo en cuenta que el mensaje de error no parece indicar qué línea del código está causando el problema, puede rastrearlo utilizando puntos de corte. Los puntos de interrupción detienen la ejecución del progtwig cuando el progtwig llega a líneas de código específicas. Al agregar puntos de interrupción a ubicaciones críticas, puede determinar qué línea de código causa el locking. Por ejemplo, si su progtwig se bloquea en una línea setContentView (), puede poner un punto de interrupción allí. Cuando el progtwig se ejecuta, se detendrá antes de ejecutar esa línea. Si luego reanudar hace que el progtwig se cuelgue antes de llegar al siguiente punto de interrupción, entonces sabrá que la línea que mató al progtwig estaba entre los dos puntos de interrupción.

Agregar puntos de interrupción es fácil si está usando Eclipse. Haga clic derecho en el margen justo a la izquierda de su código y seleccione “Alternar punto de interrupción”. Luego necesita ejecutar su aplicación en modo de depuración, el botón que parece un insecto verde al lado del botón de ejecución normal. Cuando el progtwig llegue a un punto de interrupción, Eclipse cambiará a la perspectiva de depuración y le mostrará la línea a la que está esperando. Para comenzar a ejecutar nuevamente el progtwig, busque el botón ‘Reanudar’, que se ve como un ‘Juego’ normal, pero con una barra vertical a la izquierda del triángulo.

También puede completar su solicitud con Log.d (“Mi aplicación”, “Información aquí que le indica dónde está la línea de registro”), que luego publica mensajes en la ventana de LogCat de Eclipse. Si no puede encontrar esa ventana, ábrala con Ventana -> Mostrar vista -> Otro … -> Android -> LogCat.

¡Espero que ayude!

de acuerdo con el código de windowManager (enlace aquí ), esto ocurre cuando la vista que está tratando de actualizar (que probablemente pertenece a un diálogo, pero no es necesaria) ya no se adjunta a la raíz real de las ventanas.

como otros han sugerido, debe verificar el estado de la actividad antes de realizar operaciones especiales en sus diálogos.

aquí está el código relacionado, que es la causa del problema (copiado del código fuente de Android):

 public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; view.setLayoutParams(wparams); synchronized (this) { int index = findViewLocked(view, true); ViewRootImpl root = mRoots[index]; mParams[index] = wparams; root.setLayoutParams(wparams, false); } } private int findViewLocked(View view, boolean required) { synchronized (this) { final int count = mViews != null ? mViews.length : 0; for (int i=0; i 

Mi problema se solucionó al uhlocking de la rotación de la pantalla en mi aplicación Android que me estaba causando un problema ahora funciona perfectamente

Otra opción es no iniciar la tarea asíncrona hasta que el cuadro de diálogo esté adjunto a la ventana sobrescribiendo onAttachedToWindow () en el cuadro de diálogo, de ese modo siempre es descartable.

O simplemente puedes agregar

 protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true, false); } 

que hará que el ProgressDialog no se cancele

La solución anterior no funcionó para mí. Entonces, lo que hice fue tomar ProgressDialog globalmente y luego agregar esto a mi actividad

 @Override protected void onDestroy() { if (progressDialog != null && progressDialog.isShowing()) progressDialog.dismiss(); super.onDestroy(); } 

para que en caso de que si se destruye la actividad, el archivo de progreso también se destruya.

cuando declaras actividad en el manifiesto necesitas android: configChanges = “orientation”

ejemplo:

  

Por qué no intentar atrapar, así:

 protected void onPostExecute(Object result) { try { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } } catch (Exception ex) { Log.e(TAG, ex.getMessage(), ex); } }