Android AsyncTask no se detendrá cuando se cancela, ¿por qué?
Tengo un AsyncTask que cierro en el evento de ciclo de vida de OnPause de la actividad, por lo que no se ejecuta cuando alguien deja la aplicación, pero continúa a pesar de esto. He añadido algún rastreo y este fragmento muestra el problema.
Trace.d(TAG,"Task state: " + myTask.getStatus() ); myTask.cancel(true); Trace.d(TAG,"Task state: " + myTask.getStatus() );
Salidas:
- Cuál es mejor: Loader o Fragmentos sin cabeza
- Cómo extender desde AsyncTask como una clase base genérica?
- NetworkOnMainThreadException
- Utilizar AsyncTask para cargar imágenes en ListView
- Cómo realizar operaciones de base de datos mediante Async Task
Task state: RUNNING Task state: RUNNING
¿Por qué el método cancel () no tiene ningún efecto en el estado de la tarea? Observo que los docs dicen que el método de cancelación "intentará" detener la tarea, pero bajo qué circunstancias fallará? La tarea se está ejecutando definitivamente, ya que es salida salida de registro cada diez segundos, y como se puede ver por encima de su estado se devuelve como ejecución.
Actualización: agregé el rastreo para mostrarme el estado isCancelled () también y que cambia. Así que la llamada a cancelar (true) está cambiando el estado cancelado de falso a verdadero, pero aparentemente no tiene ningún efecto en el estado, o detener el hilo.
- ¿Se está destruyendo la actividad porque la orientación ha cambiado o porque la aplicación se está cerrando?
- Cómo obtener el resultado de OnPostExecute () en la actividad principal porque AsyncTask es una clase aparte?
- Android: descarga el archivo desde el servidor y muestra el progreso de la descarga en la barra de notificación mediante AsyncTask
- Necesita mostrar la pantalla de carga mientras el servidor de consultas de aplicaciones
- Android 4.0 asynctask al mismo tiempo no es posible
- ¿Debo llamar a super () al sustituir el constructor de AsyncTask?
- AsyncTask execute () o executeOnExecutor ()?
- Pantalla de inicio de sesión que muestra progressdialog y permite cambiar la orientación de la pantalla
Tenga en cuenta que su Actividad y su AsyncTask son dos subprocesos separados. Así que incluso si cancela el AsyncTask, el código para cancelar la tarea no se puede ejecutar todavía! Es por eso que está viendo el AsyncTask todavía funcionando incluso después de corregir su error. No creo que el estado cambie hasta que doInBackground()
en su AsyncTask se haya completado. (Así que asegúrese de que está revisando isCancelled()
y volver temprano cuando se ha cancelado!)
Hice más profundo y recordé que mi hilo estaba llamando a un método bastante mal escrito que contenía esto, produciendo otro hilo dentro del que necesito cancelar:
public static void haveASleep(int milliseconds) { try { Thread.sleep(milliseconds); } catch (InterruptedException ie) { Trace.w(TAG,"Sleep interrupted"); } }
Así que lo que estaba sucediendo era que el hilo de AsyncTask llama a este método para esperar un rato, y durante el sueño la llamada del método de cancel () ocurre en el AsyncTask, que causa una excepción en el sueño del hilo. Mi código unhelpfully capturado y absorbido que la excepción, en lugar de usarlo para apagar el AsyncTask.
La solución era buscar una excepción en el sueño, y si se lanza, para salir en silencio el hilo. La aplicación funciona ahora como se esperaba, PERO …
El estado inmediatamente después de la llamada al método cancel () sigue siendo RUNNING, pero sospecho que esto es porque en ese momento todavía está en ejecución, y el sistema operativo aún no lo ha cerrado. No tengo ni idea de si eso es cierto, pero esa es mi mejor estimación.
thread.cancel(true);
Sólo establece una variable en la clase AsyncTask. Lo que debe hacer es implementar un bucle en su tarea de fondo si no lo ha hecho ya. A continuación, compruebe y rompa el bucle si cancelar es cierto para cada iteración.
@Override protected Void doInBackground(Void... params) { synchronized(this) { for(int i = 0; i < 9000; i++) { if(thread.isCancelled()) break; // do stuff } } }
A continuación, sólo tiene que cancelar siempre que lo necesite para detener. A continuación, se detendrá antes de la siguiente iteración.
@Override public void onStop() { super.onStop(); thread.cancel(true); } @Override public void onDestroy() { super.onDestroy(); thread.cancel(true); }
Incluso si sabe cómo funciona cancelar es muy difícil determinar en qué estado se detendrá su hilo. Por lo tanto, sugiero implementar su propia forma segura de detener el hilo, por lo que estará seguro en qué estado se está deteniendo y asegúrese de que no hay fugas de memoria, etc De más información cómo detener un hilo en java en caja fuerte Manera de comprobar este hilo ¿Cómo abortar un hilo de una manera rápida y limpia en java?
Otro error posible para comprobar si se está ejecutando en este problema:
Asegúrese de no iniciar dos AsyncTasks.
- Uso de PowerMock y Robolectric – IncompatibleClassChangeError
- ¿Cómo pellizcar zoom imagen en zoom de imagen android?