Todos los que prueban el desarrollo de Android descubren la importancia de la concurrencia. La única forma de crear una aplicación receptiva es dejar el subproceso de la interfaz de usuario lo más libre posible, permitiendo que todo el trabajo duro se realice de forma asincrónica mediante subprocesos de fondo..
Debido al diseño de Android, la gestión de subprocesos utiliza solo el java.lang.thread
y java.util.concurrent
Los paquetes pueden ser realmente difíciles. El uso de los paquetes de subprocesos de bajo nivel con Android significa que debe preocuparse por una gran cantidad de sincronización complicada para evitar las condiciones de carrera. Afortunadamente, la gente de Google hizo el trabajo duro y construyó algunas herramientas excelentes para facilitar nuestros trabajos: AsyncTask
, Servicio de Intención
, Cargador
, AsyncQueryHandler
y CursorLoader
Son todos útiles, así como las clases de HaMeR. Entrenador de animales
, Mensaje
, y Ejecutable
. Hay muchas opciones excelentes para elegir, cada una con sus ventajas y desventajas..
Mucho se ha dicho sobre el AsyncTask
objeto, y muchas personas lo utilizan como un bala de plata Solución para la concurrencia en Android. Es extremadamente útil para operaciones cortas, fáciles de implementar y, probablemente, el enfoque más popular para la concurrencia en Android. Si quieres aprender más sobre AsyncTask
, Echa un vistazo a las siguientes publicaciones de Envato Tuts +.
sin embargo, AsyncTask
No debería ser la única herramienta en su cinturón de herramientas..
Para operaciones de larga duración, para problemas complejos de concurrencia o para lograr una mayor eficiencia en algunas situaciones, debe elegir otra solución. Si necesita más flexibilidad o eficiencia que AsyncTask
proporciona, usted podría utilizar el HaMeR (Entrenador de animales
, Mensaje
Y Ejecutable
) marco de referencia.En este tutorial exploraremos el marco de HaMeR, uno de los modelos de concurrencia más potentes disponibles en Android, y aprenderemos cuándo y cómo usarlo. En un tutorial de seguimiento, le mostraré cómo codificar una aplicación para probar algunas posibilidades de HaMeR.
La siguiente sección presentará la importancia de los hilos de fondo para el sistema Android. Si está familiarizado con este concepto, siéntase libre de omitirlo e ir directamente a la discusión del marco de HaMeR en la sección 3.
Cuando se inicia una aplicación de Android, el primer subproceso generado por su proceso es el subproceso principal, también conocido como subproceso de la interfaz de usuario, que es responsable de manejar toda la lógica de la interfaz de usuario. Este es el hilo más importante de una aplicación. Es responsable de manejar toda la interacción del usuario y también de "atar" las partes móviles de la aplicación. Android toma esto muy en serio, y si su hilo de UI se atasca trabajando en una tarea por más de unos pocos segundos, la aplicación se bloqueará.
[El subproceso de la interfaz de usuario] es muy importante porque se encarga de enviar eventos a los widgets de interfaz de usuario adecuados, incluidos los eventos de dibujo. También es el hilo en el que su aplicación interactúa con los componentes del kit de herramientas de la interfaz de usuario de Android (componentes de laandroid.widget
yandroid.view
paquetes). Como tal, el hilo principal a veces también se llama el hilo de la interfaz de usuario. - Procesos e hilos, Guía del desarrollador de Android
El problema es que casi todo el código en una aplicación de Android se ejecutará en el subproceso de la interfaz de usuario de forma predeterminada. Dado que las tareas en un hilo se realizan de forma secuencial, esto significa que su interfaz de usuario podría 'congelarse', y dejar de responder mientras se procesa otro trabajo..
Las tareas de larga ejecución llamadas en la interfaz de usuario probablemente serán fatales para su aplicación, y aparecerá un cuadro de diálogo ANR (aplicación que no responde). Incluso las tareas pequeñas pueden comprometer la experiencia del usuario, por lo tanto, el enfoque correcto es eliminar todo el trabajo posible del subproceso de la interfaz de usuario usando subprocesos en segundo plano. Como se dijo anteriormente, hay muchas maneras de resolver este problema, y exploraremos el marco de HaMeR, una de las soluciones principales provistas por Android para enfrentar esta situación..
El marco de HaMeR permite que los subprocesos en segundo plano envíen mensajes o publiquen runnables en el subproceso de la IU y en cualquier otro subproceso Cola de mensajes
a través de los controladores. HaMeR se refiere a Entrenador de animales
, Mensaje
, Y Ejecutable
. También hay algunas otras clases importantes que trabajan junto con el HaMeR: Looper
y Cola de mensajes
. Juntos, esos objetos son responsables de facilitar la administración de subprocesos en Android, cuidar la sincronización y proporcionar métodos fáciles para que los subprocesos de fondo se comuniquen con la interfaz de usuario y con otros subprocesos..
Aquí es cómo las clases en el marco de HaMeR encajan.
Looper
ejecuta un bucle de mensaje en un hilo usando el Cola de mensajes
.Cola de mensajes
contiene una lista de mensajes a ser enviados por el Looper
.Entrenador de animales
permite el envío y procesamiento de Mensaje
y Ejecutable
al Cola de mensajes
. Se puede utilizar para enviar y procesar mensajes entre hilos..Mensaje
contiene una descripción y datos que pueden enviarse a un controlador.Ejecutable
representa una tarea a ejecutar.Con el marco de trabajo de HaMeR, los subprocesos pueden enviar mensajes o publicar objetos ejecutables a sí mismos o al subproceso de la interfaz de usuario. HaMeR también promueve interacciones de hilo de fondo a través de Entrenador de animales
.
Entrenador de animales
es el caballo de batalla HaMeR. Es responsable de enviar Mensaje
(mensaje de datos) y post Ejecutable
(mensaje de tarea) objetos a la Cola de mensajes
asociado con un Hilo
. Después de entregar las tareas a la cola, el controlador recibe los objetos de la Looper
y procesa los mensajes en el momento adecuado utilizando el Entrenador de animales
asociado a ello.
UNA Entrenador de animales
Se puede utilizar para enviar o publicar. Mensaje
y Ejecutable
objetos entre hilos, siempre que dichos hilos compartan el mismo proceso. De lo contrario, será necesario crear una Comunicación entre procesos (IPC), una metodología que supera el alcance de este tutorial..
UNA Entrenador de animales
siempre debe estar asociado con una Looper
, y esta conexión debe hacerse durante su instanciación. Si no proporciona una Looper
al Entrenador de animales
, estará ligado a la corriente Hilo
es Looper
.
// Handler usa el handler Loler Handler handler actual = new Handler (); // Handler usa el Looper, proporciona Handler handler = new Handler (Looper);
Tenga en cuenta que un Entrenador de animales
siempre se asocia con un Looper
, y esta conexión es permanente y no se puede cambiar una vez establecida. Sin embargo, un Looper
El hilo puede tener asociaciones con múltiples Entrenador de animales
s. También es importante tener en cuenta que un Looper
Debe estar activo antes de su asociación con un Entrenador de animales
.
El trabajo cooperativo entre Looper
y Cola de mensajes
en un hilo de Java crea un bucle de tareas que se procesan secuencialmente. Dicho bucle mantendrá vivo el hilo mientras espera recibir más tareas. Un hilo solo puede tener uno. Looper
y uno Cola de mensajes
asociado a ello; sin embargo, puede haber múltiples manejadores para cada hilo. Los manejadores son responsables de procesar las tareas en la cola, y cada tarea sabe qué manejador es responsable de su procesamiento.
La UI o el subproceso principal es el único tipo de subproceso que, de forma predeterminada, ya tiene una Entrenador de animales
, una Looper
, y un Cola de mensajes
. Se deben preparar otros subprocesos con esos objetos antes de que puedan funcionar con el marco de trabajo de HaMeR. Primero necesitamos crear un Looper
que ya incluye un Cola de mensajes
y adjuntarlo al hilo. Puedes hacer esto con una subclase de Hilo
, como sigue.
// Preparando un tema para la clase HaMeR LooperThread extiende el tema public Handler mHandler; public void run () // agregar y preparar el Looper Looper.prepare (); // la instancia de Handler se asociará con Thread's Looper mHandler = new Handler () public void handleMessage (Message msg) // procesa los mensajes entrantes aquí; // Iniciar el bucle de cola de mensajes utilizando el Looper Looper.loop ();
Sin embargo, es más sencillo usar una clase de ayuda llamada HandlerThread
, que tiene un Looper
y un Cola de mensajes
construido en un Java Hilo
y está listo para recibir un controlador.
// La clase HandlerThread incluye una clase pública de Looper HamerThread extendida HandlerThread // solo necesita agregar el controlador Handler private Handler; HamerThread público (nombre de cadena) super (nombre);
los Ejecutable
Es una interfaz de Java que tiene muchos usos. Podría entenderse como una sola tarea a realizar en una Hilo
. Tiene un solo método que debe ser implementado., Runnable.run ()
, para realizar la tarea.
// Declarar un Runnable Runnable r = new Runnable () @Override public void run () // la tarea va aquí;
Hay múltiples opciones para publicar una Ejecutable
en un Entrenador de animales
.
Handler.post (Runnable r)
: añade el Ejecutable
al Cola de mensajes
.Handler.postAtFrontOfQueue (Runnable r)
: añade el Ejecutable
en el frente de la Cola de mensajes
.Entrenador de animales.postAtTime (Runnable r, long timeMillis)
: añade el Ejecutable
sobre el Cola de mensajes
para ser llamado en un momento específico.Entrenador de animales.postDelayed (Runnable r, long delay)
: añade el Ejecutable
a la cola que se llamará después de que haya transcurrido un tiempo específico.// publicar un Runnable en un Handler Handler handler = new Handler (); handler.post (new Runnable () @Override public void run () // task goes here);
También es posible utilizar el controlador de UI predeterminado para publicar un Ejecutable
vocación Activity.runOnUiThread ()
.
// publicar Runnable usando el UI Handler Activity.runOnUiThread (new Runnable () @Override public void run () // task to perform);
Es importante tener en cuenta algunas cosas acerca de Ejecutable
s. A diferencia de un Mensaje
, una Ejecutable
no se puede reciclar, una vez que se termina su trabajo, está muerto. Ya que es parte de un paquete estándar de Java, un Ejecutable
no depende de Entrenador de animales
y puede ser llamado en un estándar Hilo
utilizando la Runnable.run ()
método. Sin embargo, este enfoque no tiene nada que ver con el marco de HaMeR y no compartirá ninguna de sus ventajas..
los Mensaje
El objeto define un mensaje que contiene una descripción y algunos datos arbitrarios que se pueden enviar y procesar a través de Entrenador de animales
. los Mensaje
se identifica con una En t
definido en Message.what ()
. los Mensaje
puede contener otros dos En t
argumentos y un Objeto
para almacenar diferentes tipos de datos.
Mensaje
: En t
identificando el Mensaje
Mensaje.arg1
: En t
argumento arbitrarioMensaje.arg2
: En t
argumento arbitrarioMensaje.obj
: Objeto
para almacenar diferentes tipos de datos Cuando necesite enviar un mensaje, en lugar de crearlo desde cero, el método recomendado es recuperar uno reciclado directamente del grupo global con el Mensaje.obtain ()
o Handler.obtainMessage ()
comandos Hay algunas versiones diferentes de esos métodos que le permiten obtener una Mensaje
de acuerdo a su necesidad.
Un uso común de Handler.obtainMessage ()
es cuando necesitas enviar un mensaje a un hilo de fondo. Vas a utilizar el Entrenador de animales
asociado con ese hilo Looper
para obtener un Mensaje
y enviarlo al hilo de fondo, como en el siguiente ejemplo.
int what = 0; String hello = "Hello!"; // Obtención de un mensaje asociado con un mensaje de subproceso de fondo msg = handlerBGThread.obtainMessage (what, hello); // Enviando el mensaje al controlador de subproceso de fondoBGThread.sendMessage (msg);
Hay muchos métodos geniales en Mensaje
clase, y le aconsejo que eche un vistazo más de cerca a la documentación.
enviar mensaje()
OpcionesDe manera similar a como podemos publicar Ejecutable
s, hay multiples opciones para enviar Mensaje
s:
Handler.sendMessage (Mensaje msg)
: Agrega un Mensaje
al Cola de mensajes
.Handler.sendMessageAtFrontOfQueue (Mensaje msg)
: Agrega un Mensaje
al frente de la Cola de mensajes
.Handler.sendMessageAtTime (Mensaje msg, long timeInMillis)
: Agrega un Mensaje
a la cola en un momento específico.Handler.sendMessageDelayed (Mensaje msg, long timeInMillis)
: Agrega un Mensaje
a la cola después de que haya pasado un tiempo específico.los Mensaje
objetos despachados por Looper
Son procesados por el manejador con el método. Handler.handleMessage
. Todo lo que tienes que hacer es extender el Entrenador de animales
Clase y anular este método para procesar los mensajes..
public class MessageHandler extiende Handler @Override public void handleMessage (Message msg) switch (msg.what) // handle 'Hello' msg case 0: String hello = (String) msg.obj; System.out.println (hola); descanso;
El marco de HaMeR puede ayudar a mejorar el código concurrente de su aplicación Android. Puede parecer confuso al principio en comparación con la simplicidad de un AsyncTask
, pero la apertura de HaMeR puede ser una ventaja, si se usa correctamente.
Recuerda:
Handler.post ()
Los métodos se utilizan cuando los remitentes saben qué operaciones realizar..Handler.sendMessage()
Los métodos se utilizan cuando el receptor sabe qué operación realizar..Para obtener más información sobre el subprocesamiento en Android, puede interesarle el libro Efficient Android Threading: Técnicas de procesamiento asíncrono para aplicaciones de Android por Anders Goransson.
En el siguiente tutorial, continuaremos explorando el marco de HaMeR con un enfoque práctico, mediante la creación de una aplicación que demuestre diferentes formas de usar este marco de concurrencia de Android. Crearemos esta aplicación desde cero, probando diferentes posibilidades, como la comunicación entre Trapos
, hablar con el hilo de la interfaz de usuario, así como enviar mensajes y publicar Ejecutable
s con retrasos.
Te veo pronto!