periodically - android background service library
Consideraciones de diseño de android: AsyncTask vs Service(IntentService?) (5)
Con AsyncTask
si el usuario va a otra actividad, no puede transferir ese objeto a la otra actividad por lo que muere. Hay trucos que puedes jugar cuando el usuario rota la pantalla o algo así, pero eso no se extiende a la destrucción general. AsyncTask
puede morir al azar.
Google Sync se ejecuta como un Servicio en segundo plano porque la sincronización puede tardar un poco en completarse. Es posible que deba seguir su ruta y crear su propio servicio de sincronización con el que pueda comunicarse. Aquí hay algunos pensamientos de cómo lograr eso:
http://mylifewithandroid.blogspot.com/2008/01/about-binders.html
Definitivamente puedes comunicarte entre Servicio y Actividad, pero es difícil hacerlo bien.
Estoy diseñando una aplicación de Android que tendrá que hacer los siguientes pasos:
- el usuario presiona un botón o indica "sincronizar datos".
- el proceso de sincronización utilizará los servicios web REST para mover datos hacia y desde el servidor.
- Los datos se almacenarán localmente en una base de datos sqlite.
- el proceso de sincronización debe proporcionar actualizaciones / mensajes de estado a la interfaz de usuario
- No se debe permitir al usuario vagar a otras partes de la aplicación y hacer más trabajo durante el proceso de sincronización.
La primera vez que se ejecuta el proceso de sincronización, puede llevar entre 10 y 20 minutos. Después de la sincronización inicial, se transferirán y almacenarán menos datos y espero que el proceso demore de 1 a 2 minutos o menos.
He estado leyendo mucho sobre AsyncTask
de AsyncTask
y varios ejemplos de uso de un Servicio ... Pero no entiendo completamente las consideraciones de diseño y las concesiones de elegir un diseño sobre otro. Actualmente tengo mi proyecto de demostración eliminado usando una AsyncTask. Después de ver (la mayoría de) Desarrollar aplicaciones cliente REST de Android: http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html# Me quedo confundido con los patrones de diseño descritos aquí siento demasiado complejo, tal vez porque simplemente "no lo entiendo" todavía.
Vengo de Java, Spring, Web y fondo de aplicaciones de escritorio. Pensar y diseñar en términos de un dispositivo de mano es bastante nuevo para mí. (¿Qué sucede cuando se cambia el diseño de la pantalla? ¿Qué sucede cuando suena el teléfono mientras estoy ejecutando una sincronización?) Retroceder 2 pasos, si la sincronización inicial va a ser un proceso de ejecución tan largo, ¿hay una mejor manera de hacerlo? ¿Debo pensar en la solución del problema, la experiencia del usuario, las expectativas del usuario de una aplicación que se ejecuta en un teléfono?
Me encantaría saber de algunos desarrolladores de Android más experimentados que ya han luchado con estas preguntas.
En mi opinión, esta es la parte más difícil / difícil de un desarrollo de Android estándar / promedio. Por ejemplo, en BlackBerry esto es EN TIEMPO más fácil.
Definitivamente necesitas utilizar un Service
.
AsyncTask
no se adapta, ya que está estrechamente "vinculada" a su Activity
través de un controlador de Context
(de lo contrario, no podría actualizar la IU de la Activity
desde su AsyncTask
). Sin embargo, una Activity
puede ser eliminada por el sistema operativo una vez que la Activity
fue en segundo plano. Una razón de ejemplo para pasar al fondo puede ser una llamada entrante: el usuario cambia a la aplicación Teléfono para que su Activity
vuelva invisible. En este caso (dependiendo del estado actual de la RAM), el sistema operativo puede decidir eliminar una de las actividades de fondo (invisibles para el usuario).
Algunos desarrolladores solucionan esto organizando cosas estáticas para realizar acciones de larga duración dentro de. Algunos recomiendan usar la instancia de la Application
. Esto se debe a que existen cosas estáticas y Application
mientras existe todo el proceso de la aplicación. Sin embargo, esas son soluciones alternativas incorrectas. Los procesos en Android también se pueden eliminar cuando el SO decide que es hora de hacerlo. El sistema operativo Android tiene sus propias consideraciones sobre lo que puede matar y en qué orden. Todos los procesos se dividen en 5 niveles de "habilidad". Aquí está el documento donde se especifican esos niveles. Es interesante leer allí:
Debido a que un proceso que ejecuta un servicio tiene una clasificación más alta que uno con actividades en segundo plano, una actividad que inicie una operación de larga duración podría hacer bien para iniciar un servicio para esa operación, en lugar de simplemente generar un subproceso, especialmente si la operación probablemente durará más que la actividad. Ejemplos de esto son reproducir música en segundo plano y cargar una imagen tomada por la cámara a un sitio web. El uso de un servicio garantiza que la operación tendrá al menos prioridad de "proceso de servicio", independientemente de lo que suceda con la actividad.
Su Activity
donde los usuarios inician una acción de larga duración debe mostrar un ProgressDialog
para asegurarse de que el usuario no haga nada más mientras se ejecuta la acción. La guía está here .
Además, lo más probable es que desee utilizar el NotificationManager
para notificar al usuario sobre la finalización (o falla) de su acción de larga ejecución si su Activity
es actualmente invisible. Aquí está la información de NotificationManager para comenzar.
Hay varias consideraciones que debe sopesar para decidir mejor cómo abordar su situación. Parece que necesita una buena comparación entre los dos enfoques ... Así que aquí hay una lista de similitudes, y diferencias y consideraciones adicionales que deben tenerse en cuenta al trabajar en un dispositivo portátil.
Un servicio es una parte de su aplicación que no tiene una interfaz de usuario. Puede ser llamado por una UI (Actividad) para iniciarse, o puede ser iniciado por cualquier otro componente de su Aplicación. Al desarrollar, tiene la libertad de colocarlo en un subproceso diferente, o incluso ejecutarlo en una Tarea o Proceso diferente. Esto le permite finalmente separarlo de su interfaz de usuario. Además, puede iniciar el Servicio para que se ejecute de forma independiente (startService) o vincular su actividad a él (bindService) según sus necesidades. Al usar manejadores personalizados, puede configurar las devoluciones de llamada para actualizar la interfaz de usuario con su progreso. Un Servicio no necesariamente termina si un Usuario cambia de Actividades, pero el SO puede finalizar en CUALQUIER momento.
A AsyncTask siempre se crea una instancia del subproceso de la interfaz de usuario. Solo permite devoluciones de llamadas específicas, pero simplifica el proceso de subprocesos múltiples con el fin de realizar transacciones relativamente cortas (en comparación con servicios de subprocesos separados dedicados) que están inherentemente vinculados a acciones realizadas por una actividad. Cada vez que un Usuario cambia de Actividades, la AsyncTask se pone en "pausa" y puede incluso morir porque ya no hay un hilo de UI para su Actividad.
Lo que más me preocupa es que si la aplicación se demorara entre 10 y 20 minutos la primera vez, ASUMIRÍA que el Usuario cambiará las tareas temporalmente o apagará el teléfono hasta que se complete (lo que puede causar todo) las mismas complicaciones si el teléfono duerme). Teniendo en cuenta esta consideración, un servicio por hilos vinculado a su actividad puede ser su mejor opción. Para proteger su UI, haría un diálogo de progreso para su actividad que recibe sus devoluciones de llamada de progreso. Esto limita la entrada del usuario en SU aplicación y le permite a su servicio continuar de la manera que necesita. Luego, anule la Actividad onResume para verificar el estado de su Servicio y si se está ejecutando. A continuación, puede restablecer el diálogo inmediatamente.
Dado que este es mi método preferido, también tomaría en cuenta que el sistema operativo puede matar la aplicación en cualquier momento de todos modos. Así que asegúrate de tener alguna forma de detectar una sincronización incompleta o parcial. Entonces puede reanudar automáticamente cuando se reinicia su actividad o servicio.
La elección depende principalmente del diseño de la aplicación. Dado que tanto AsyncTask como IntentService se mantienen firmes, lo más importante es que lo que desee de la aplicación (experiencia del usuario) sea más importante y luego elija uno o ambos. Algunos escenarios se mencionan a continuación (principalmente lo que experimenté al desarrollar aplicaciones)
Suponga que las aplicaciones tienen páginas de fuentes: donde se realizan más de una llamada a la API para hacer que la página sea presentable (/ getFriends, / getDates, / getPictures, etc.) puede deformar todas las llamadas de la API a una sola AsyncTask con un ejecutor que es multiproceso. La secuencia de ejecución no importa. A diferencia de IntentService, que ejecuta todas las llamadas en secuencia en un solo subproceso de trabajo. Para un dispositivo de gama alta con varios núcleos, la llamada desde AsyncTask es más efectiva. Y si inicia AsyncTask en el subproceso de la interfaz de usuario, la actualización de IU es un pedazo de pasteles (lea el código de la placa de la caldera). E incluso si un usuario abandona la página, con el uso inteligente de no mantener el contexto, la aplicación no falla.
Suponiendo que está intentando escribir una aplicación que no necesita que el usuario esté en la vista / actividad / fragmento y que el tiempo total de ejecución para mostrar algo no es de misión crítica (suponga que el servicio de sincronización o la notificación / alarma del usuario), entonces IntentService es mejor elección. (No hay problemas para iniciar Asynctask en el hilo de la IU para que no tenga que escribir un controlador para forzar cambios en la IU, etc., y menos código de placa de caldera)
Desde mi experiencia, escriba una aplicación pequeña para ambos y compare los pros y los contras para tener una mejor idea. (PD: sugiero que eche un vistazo a la aplicación iosched de google para tener una mejor idea: usan Asynctask e IntentService)
Tiendo a preferir el combo IntentService + BroadcastReceiver porque te dan un gran grado de control.
Definitivamente, debe asegurarse de que la interfaz de usuario se esté ejecutando si está actualizando algo en la pantalla. Los choques de ASyncTask se reportaron de inmediato como una de las principales causas de los choques de Android. Esto se puede evitar manteniendo algún tipo de variable "activityIsAlive" y omitiendo o retrasando una actualización de UI si la actividad está muerta.
El combo IntentService + BroadcastReceiver es un poco más resistente al bloqueo porque la mayoría de los tutoriales le dicen que apague BroadcastReceiver onPause o onStop. Si no lo hace, nuevamente deberá desactivar la actualización de la interfaz de usuario. Hay un comando runOnUiThread en algún lugar que te ayudará a realizar las actualizaciones de la interfaz de usuario.
El combo IntentService + BroadcastReceiver también es más extensible. Puede crear funciones y extender BroadcastReceiver para hacer una solución de procesamiento REST más elegante. Sin embargo, requiere más plomería en comparación con una ASyncTask
Si demora la actualización de la interfaz de usuario, es posible que pueda instalarla en OnWindowFocusChangedListener. Cuando esa función recibe verdadero, significa que la interfaz de usuario está viva.
tldr; Asegúrese de que la actividad y / o el fragmento estén vivos antes de actualizar la interfaz de usuario si está ejecutando algo en segundo plano
Edición de 2015: echa un vistazo a los cargadores también. Un poco más difícil de entender porque hay muchas cosas detrás de las escenas