Tengo una actividad que inicia AsyncTask y muestra el diálogo de progreso durante la duración de la operación. La actividad se declara como NO recreada mediante rotación o deslizamiento del teclado.
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
Una vez que se completa la tarea, descarto el diálogo, pero en algunos teléfonos (framework: 1.5, 1.6) se produce dicho error:
java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201)
at android.view.Window$LocalWindowManager.removeView(Window.java:400)
at android.app.Dialog.dismissDialog(Dialog.java:268)
at android.app.Dialog.access$000(Dialog.java:69)
at android.app.Dialog$1.run(Dialog.java:103)
at android.app.Dialog.dismiss(Dialog.java:252)
at xxx.onPostExecute(xxx$1.java:xxx)
Mi código es:
final Dialog dialog = new AlertDialog.Builder(context)
.setTitle("Processing...")
.setCancelable(true)
.create();
final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() {
@Override
protected MyResult doInBackground(MyParams... params) {
// Long operation goes here
}
@Override
protected void onPostExecute(MyResult result) {
dialog.dismiss();
onCompletion(result);
}
};
task.execute(...);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface arg0) {
task.cancel(false);
}
});
dialog.show();
Por lo que he leído ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html ) y visto en las fuentes de Android, parece que la única situación posible para obtener eso La excepción es cuando la actividad fue destruida. Pero como he mencionado, prohíbo la recreación de actividades para eventos básicos.
Entonces cualquier sugerencia es muy apreciada.
Respuestas:
A veces también recibo este error cuando descarto el diálogo y finalizo la actividad del método onPostExecute. Supongo que a veces la actividad termina antes de que el diálogo se cierre correctamente.
Solución simple pero efectiva que funciona para mí.
fuente
Aquí está mi solución "a prueba de balas", que es una compilación de todas las buenas respuestas que encontré sobre este tema (gracias a @Damjan y @Kachi). Aquí la excepción se traga solo si todas las otras formas de detección no tuvieron éxito. En mi caso, necesito cerrar el diálogo automáticamente y esta es la única forma de proteger la aplicación de un bloqueo. ¡Espero que te ayude! Por favor, vote y deje comentarios si tiene comentarios o una mejor solución. ¡Gracias!
fuente
dialog = null
no tiene ningún efecto. YStatusEventDialog
debería leer soloDialog
.isDestroyed()
que no esté disponible, pero a efectos prácticos, ¿no sería lo mismo usar try / catch siempre?Puedo tener una solución alternativa.
Estaba teniendo el mismo problema, donde estoy cargando muchos artículos (a través del sistema de archivos) en una
ListView
víaAsyncTask
. Tenía elonPreExecute()
encendido aProgressDialog
, y luego ambosonPostExecute()
yonCancelled()
(llamado cuando la tarea se cancela explícitamente a través deAsyncTask.cancel()
) cerrándolo a través de.cancel()
.Obtuve el mismo error "java.lang.IllegalArgumentException: vista no adjunta al administrador de ventanas" cuando estaba eliminando el diálogo en el
onCancelled()
método deAsyncTask
(había visto esto en la excelente aplicación de Shelves ).La solución era crear un campo público en el
AsyncTask
que contengaProgressDialog
:Luego,
onDestroy()
cuando cancelo miAsyncTask
, también puedo eliminar el diálogo asociado a través de:Llamar a
AsyncTask.cancel()
DOES se activaonCancelled()
en elAsyncTask
, pero por alguna razón para el momento en que se llama al método, la Vista ya se ha destruido y, por lo tanto, la cancelación del diálogo está fallando.fuente
Aquí está la solución correcta para resolver este problema:
En lugar de detectar ciegamente todas las excepciones, esta solución aborda la raíz del problema: tratar de atenuar un diálogo cuando la actividad utilizada para inicializar el diálogo ya ha finalizado. Trabajando en mi Nexus 4 con KitKat, pero debería funcionar para todas las versiones de Android.
fuente
isDestroyed
requiere API 17+Acepto una opinión de 'Damjan'.
si usa muchos cuadros de diálogo, debería cerrar todos los cuadros de diálogo en onDestroy () o onStop ().
entonces es posible que pueda reducir la frecuencia de la excepción 'java.lang.IllegalArgumentException: vista no adjunta al administrador de ventanas'.
pero poco excede ...
para que quede más claro, evita mostrar cualquier diálogo después de que onDestroy lo llame.
No uso como a continuación. Pero está claro.
¡buena suerte!
fuente
Utilizar este.
fuente
if
en casos como este, el&&
operador de Java tiene una evaluación diferida (también llamada cortocircuito), lo que significa que el segundo operando no se evalúa si el primero evalúafalse
(lo que significa el resultado de la&&
siempre habráfalse
de todos modos, por lo tanto, la evaluación "perezosa"). Del mismo modo||
, no evaluará su segundo operando si el primero se evalúa comotrue
. Nota: los operadores&
y|
no tienen este comportamiento y, por lo tanto, siempre evalúan ambos operandos.Tuve el mismo problema, puedes resolverlo de la siguiente manera:
fuente
Creo que su código es correcto a diferencia de la otra respuesta sugerida. onPostExecute se ejecutará en el hilo de la interfaz de usuario. Ese es el objetivo de AsyncTask: no tiene que preocuparse por llamar a runOnUiThread o tratar con controladores. Además, de acuerdo con los documentos, se puede invocar de forma segura desde cualquier subproceso (no estoy seguro de que hayan hecho de esto la excepción).
¿Quizás es un problema de tiempo donde se llama a dialog.dismiss () después de que la actividad ya no se muestra?
¿Qué pasa con la prueba de lo que sucede si comenta el setOnCancelListener y luego sale de la actividad mientras se ejecuta la tarea en segundo plano? Entonces su onPostExecute intentará descartar un diálogo ya descartado. Si la aplicación falla, probablemente pueda verificar si el cuadro de diálogo está abierto antes de cerrarlo.
Tengo exactamente el mismo problema, así que voy a probarlo en código.
fuente
alex,
Podría estar equivocado aquí, pero sospecho que varios teléfonos 'en estado salvaje' tienen un error que hace que cambien de orientación en aplicaciones que están marcadas como orientadas estáticamente. Esto sucede bastante en mi teléfono personal y en muchos de los teléfonos de prueba que usa nuestro grupo (incluidos droide, n1, g1, héroe). Por lo general, una aplicación marcada como estáticamente orientada (tal vez verticalmente) se presentará por un segundo o dos utilizando una orientación horizontal, y luego cambiará de inmediato. El resultado final es que, aunque no desea que su aplicación cambie de orientación, debe estar preparado para que así sea. No sé en qué condiciones exactas se puede reproducir este comportamiento, no sé si es específico de una versión de Android. Todo lo que sé es que lo he visto suceder muchas veces :(
Recomendaría usar la solución provista en el enlace que publicó que sugiere anular el método Activity onCreateDialog y dejar que el sistema operativo Android administre el ciclo de vida de sus cuadros de diálogo. Me parece que a pesar de que no desea que su actividad cambie de orientación, está cambiando de orientación en alguna parte. Puede intentar localizar un método que siempre evitará el cambio de orientación, pero estoy tratando de decirle que personalmente no creo que haya una manera infalible que funcione en todos los teléfonos Android actuales en el mercado.
fuente
Lo que funcionó para mí la mayor parte del tiempo es verificar si la Actividad no está terminando.
fuente
Acabo de tener el mismo problema. Arreglo para API nivel 13 o superior.
Desde documentos de Android:
Así que he cambiado mi manifiesto a esto:
Y ahora funciona bien. La actividad no se recrea cuando giro el teléfono, el diálogo de progreso y la vista permanecen igual. No hay error para mi.
fuente
En primer lugar, maneje los errores siempre que intente descartar el diálogo.
Si eso no se soluciona, descartarlo en el método onStop () de la actividad.
fuente
Tuve el mismo problema al usar un botón para sincronizar una lista del servidor: 1) Hago clic en el botón 2) Aparece un cuadro de diálogo de progreso al descargar la lista del servidor 3) Giro el dispositivo a otra orientación 4) java.lang .IllegalArgumentException: vista no adjunta al administrador de ventanas en postExecute () de AsyncTask durante progress.dismiss ().
Cuando probé la solución, pensé que incluso si el problema no se producía, mi lista no mostraba todos los elementos.
Pensé que lo que quería era que AsyncTask terminara (y descartara el diálogo) antes de que se destruyera la actividad, así que hice del objeto asynctask un atributo y anulé el método onDestroy ().
Si el asinctask toma mucho tiempo, el usuario tal vez sienta que el dispositivo es lento, pero creo que ese es el precio que paga por tratar de cambiar la orientación del dispositivo mientras se muestra el diálogo de progreso. E incluso si lleva algún tiempo, la aplicación no se bloquea.
fuente
fuente
Más abajo el código funciona para ti, funciona perfectamente para mí:
No defina su vista globalmente si la llama desde el servicio en segundo plano.
fuente