Puede comprender mejor qué es Looper en el contexto del marco GUI. Looper está hecho para hacer 2 cosas.
1) Looper transforma un hilo normal , que termina cuando su método run () regresa, en algo que se ejecuta continuamente hasta que se ejecuta la aplicación de Android , lo cual es necesario en el marco de la GUI (Técnicamente, todavía termina cuando el método run () regresa. Pero déjame aclarar lo que quiero decir a continuación).
2) Looper proporciona una cola donde se ponen en cola los trabajos a realizar, que también es necesario en el marco de la GUI.
Como ya sabrá, cuando se inicia una aplicación, el sistema crea un subproceso de ejecución para la aplicación, denominado "principal", y las aplicaciones de Android normalmente se ejecutan completamente en un solo subproceso por defecto, el "subproceso principal". Pero el hilo principal no es un secreto, un hilo especial . Es solo un hilo normal similar a los hilos que creas con new Thread()
código, lo que significa que termina cuando vuelve su método run (). Piense en el siguiente ejemplo.
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Ahora, apliquemos este principio simple a las aplicaciones de Android. ¿Qué pasaría si una aplicación de Android se ejecuta en hilo normal? Un hilo llamado "main" o "UI" o lo que sea que inicie su aplicación, y dibuja toda la IU. Entonces, la primera pantalla se muestra a los usuarios. ¿Y ahora qué? El hilo principal termina? No, no debería. Debería esperar hasta que los usuarios hagan algo, ¿verdad? Pero, ¿cómo podemos lograr este comportamiento? Bueno, podemos intentarlo con Object.wait()
oThread.sleep()
. Por ejemplo, el subproceso principal finaliza su trabajo inicial para mostrar la primera pantalla y duerme. Se despierta, lo que significa interrumpido, cuando se busca un nuevo trabajo para hacer. Hasta ahora todo bien, pero en este momento necesitamos una estructura de datos similar a la cola para mantener múltiples trabajos. Piense en un caso en el que un usuario toca la pantalla en serie, y una tarea tarda más en terminar. Por lo tanto, necesitamos tener una estructura de datos para mantener los trabajos a realizar de primero en entrar, primero en salir. Además, puede imaginarse que implementar un subproceso que siempre se ejecuta y procesa el trabajo cuando se llega mediante la interrupción no es fácil y conduce a un código complejo y, a menudo, imposible de mantener. Preferimos crear un nuevo mecanismo para tal propósito, y de eso se trata Looper . El documento oficial de la clase Looper.dice: "Los subprocesos por defecto no tienen un bucle de mensajes asociado con ellos", y Looper es una clase "utilizada para ejecutar un bucle de mensajes para un subproceso". Ahora puedes entender lo que significa.
Para aclarar las cosas, verifiquemos el código donde se transforma el hilo principal. Todo sucede en la clase ActivityThread . En su método main (), puede encontrar el siguiente código, que convierte un hilo principal normal en algo que necesitamos.
public final class ActivityThread {
...
public static void main(String[] args) {
...
Looper.prepareMainLooper();
Looper.loop();
...
}
}
y Looper.loop()
bucle de método infinitamente y retirar un mensaje y procesar uno a la vez:
public static void loop() {
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg);
...
}
}
Entonces, básicamente Looper es una clase hecha para abordar un problema que ocurre en el marco de la GUI. Pero este tipo de necesidades también puede ocurrir en otra situación. En realidad, es un patrón bastante famoso para la aplicación de subprocesos múltiples, y puede obtener más información al respecto en " Programación concurrente en Java " de Doug Lea (Especialmente, el capítulo 4.1.4 "Subprocesos de trabajo" sería útil). Además, puede imaginar que este tipo de mecanismo no es único en el marco de Android, pero todo el marco de la GUI puede necesitar algo similar a esto. Puede encontrar casi el mismo mecanismo en el marco de Java Swing.