studio - manual de programacion android pdf
Android AsyncTask para operaciones de larga duración (4)
Citando la documentación para AsyncTask que se encuentra here , dice
AsyncTasks debería utilizarse idealmente para operaciones cortas (unos segundos como máximo). Si necesita mantener los hilos en ejecución durante largos periodos de tiempo, se recomienda encarecidamente que utilice las diversas API proporcionadas por el paquete java.util.concurrent, como Ejecutor, ThreadPoolExecutor y FutureTask.
Ahora mi pregunta surge ¿por qué? La función doInBackground se ejecuta fuera del subproceso de interfaz de usuario. Entonces, ¿qué daño podemos tener al tener una operación de larga duración aquí?
por qué ?
Debido a que AsyncTask
, de forma predeterminada, utiliza un grupo de subprocesos que no creó . Nunca bloquee los recursos de un grupo que no creó, ya que no sabe cuáles son los requisitos del grupo. Y nunca bloquee los recursos de un grupo que no creó si la documentación de ese grupo le indica que no lo haga, como es el caso aquí.
En particular, comenzando con Android 3.2, el grupo de subprocesos utilizado por AsyncTask
de forma predeterminada (para aplicaciones con android:targetSdkVersion
establecido en 13 o más) tiene solo un hilo en él: si android:targetSdkVersion
este hilo indefinidamente, ninguna de sus otras tareas correrá.
El problema con AsyncTask es que si se define como clase interna no estática de la actividad, tendrá una referencia a la actividad. En el escenario en el que termina la actividad del contenedor de la tarea asíncrona, pero el trabajo en segundo plano en AsyncTask continúa, el objeto de actividad no se recolectará como basura, ya que hay una referencia al mismo, esto provoca la pérdida de memoria.
La solución para solucionar esto es definir una tarea asíncrona como clase de actividad interna estática y usar una referencia débil al contexto.
Pero aún así, es una buena idea usarlo para tareas de fondo simples y rápidas. Para desarrollar la aplicación con código limpio, es mejor usar RxJava para ejecutar tareas en segundo plano complejas y actualizar la IU con los resultados de la misma.
Es una muy buena pregunta, se necesita tiempo como programador de Android para comprender completamente el problema. De hecho, AsyncTask tiene dos problemas principales que están relacionados:
- Están mal vinculados al ciclo de vida de la actividad
- Crean pérdidas de memoria muy fácilmente.
Dentro de la aplicación RoboSpice Motivations ( disponible en Google Play ) contestamos esa pregunta en detalle. Proporcionará una visión detallada de AsyncTasks, Loaders, sus características y desventajas, y también le presentará una solución alternativa para solicitudes de red: RoboSpice. Las solicitudes de red son un requisito común en Android y por naturaleza son operaciones de larga duración. Aquí hay un extracto de la aplicación:
El ciclo de vida AsyncTask y Actividad
AsyncTasks no siguen el ciclo de vida de las instancias de actividad. Si inicia una AsyncTask dentro de una Actividad y gira el dispositivo, la Actividad se destruirá y se creará una nueva instancia. Pero el AsyncTask no morirá. Seguirá viviendo hasta que se complete.
Y cuando se complete, AsyncTask no actualizará la UI de la nueva Actividad. De hecho, actualiza la instancia anterior de la actividad que ya no se muestra. Esto puede llevar a una Excepción del tipo java.lang.IllegalArgumentException: Vista no asociada al administrador de ventanas si usa, por ejemplo, findViewById para recuperar una vista dentro de la Actividad.
Problema de pérdida de memoria
Es muy conveniente crear AsyncTasks como clases internas de sus Actividades. Como AsyncTask necesitará manipular las vistas de la Actividad cuando la tarea esté completa o en progreso, el uso de una clase interna de la Actividad parece conveniente: las clases internas pueden acceder directamente a cualquier campo de la clase externa.
Sin embargo, significa que la clase interna tendrá una referencia invisible en su instancia de clase exterior: la Actividad.
A largo plazo, esto produce una pérdida de memoria: si la AsyncTask dura mucho tiempo, mantiene la actividad "viva", mientras que a Android le gustaría deshacerse de ella, ya que ya no se puede mostrar. La actividad no puede ser recogida de basura y ese es un mecanismo central para que Android preserve los recursos en el dispositivo.
Realmente es una muy mala idea usar AsyncTasks para operaciones de larga ejecución. Sin embargo, están bien para los de corta vida como la actualización de una vista después de 1 o 2 segundos.
Los animo a que descarguen la aplicación RoboSpice Motivations , realmente explica esto en profundidad y proporciona ejemplos y demostraciones de las diferentes formas de realizar algunas operaciones en segundo plano.
Las tareas de sincronización son hilos especializados que aún están destinados a ser utilizados con la interfaz gráfica de usuario de la aplicación, pero al mismo tiempo mantienen tareas de recursos de la secuencia de la interfaz de usuario. Entonces, cuando cosas como actualizar listas, cambiar sus vistas, etc. requieren que realice operaciones de recuperación o actualice operaciones, debe usar tareas asíncronas para poder mantener estas operaciones fuera del hilo de la interfaz de usuario pero tenga en cuenta que estas operaciones todavía están conectadas a la IU de alguna manera .
Para las tareas que se ejecutan más a largo plazo, que no requieren la actualización de la IU, puede usar los servicios porque pueden vivir incluso sin una IU.
Por lo tanto, para tareas cortas, use tareas asíncronas porque el sistema operativo puede matarlos después de que muera su actividad de desove (generalmente no morirá a mitad de la operación pero completará su tarea). Y para tareas largas y repetitivas, use servicios en su lugar.
para más información, Ver hilos:
AsyncTask por más de unos segundos?
y
AsyncTask no se detendrá incluso cuando la actividad haya destruido