¿Cómo el Looper sabe enviar el mensaje a Handler?

La pregunta es, ¿dónde le digo a mi hilo que use mHandler para Looper ?

Gracias. Estoy utilizando el siguiente código:

class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } } 

La pregunta es, ¿dónde le digo a mi hilo que use mHandler para Looper?

Usted no necesita decirlo explícitamente, porque el sistema (framework) lo hace por usted. Al instanciar el Handler , obtendrá automáticamente acceso a la cola de mensajes de su Thread actual. Citando su comentario:

¿Cómo sabe el sistema enviar el mensaje al mHandler Handler ?

Voy a detallarlo a continuación.

Este es el constructor de android.os.Handler en Android:

  mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; 

Como puede ver, primero obtiene el Looper de su Thread actual. El código fuente de Looper.myLooper() es el siguiente:

 public static final Looper myLooper() { return (Looper)sThreadLocal.get(); } 

Lo obtiene del almacenamiento local del hilo. Más tarde, cuando envíe un Message con este Handler , el Handler realmente se establece como destinatario del Message : así es como el Looper sabrá dónde enviar el Message cuando llegue. En detalles:

Cuando llama a mHandler.sendMessage() , eventualmente este código se ejecuta (entre muchas otras líneas de código):

  MessageQueue queue = mQueue; boolean sent = false; if (queue != null) { msg.target = this; // msg is your Message instance sent = queue.enqueueMessage(msg, uptimeMillis); } 

Como puede ver, establece la instancia de Handler como destino del Message . Por lo tanto, más tarde, cuando el Message se envía, contendrá el Handler como su destino. Así es como el Looper sabrá a qué Handler debe enviarlo. En los detalles, cuando llama Looper.loop() , lo siguiente sucede para cada una de las instancias de Message en la cola:

 msg.target.dispatchMessage(msg); 

El código dispatchMessage() es el siguiente:

 public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } 

Observe la última handleMessage(msg) – esto es exactamente su handleMessage(msg) !

Para tener una mejor comprensión, cree un Thread normal e intente crear un Handler en el método run() de ese subproceso. Obtendrá una RuntimeException diciendo:

No se puede crear el controlador dentro de hilo que no ha llamado Looper.prepare()

Ahora llamar a Looper.prepare () en el método run() antes de crear un Handler crearía un nuevo objeto Looper asociado con el subproceso llamante . La fuente de su confusión es que Looper.prepare () no toma un argumento como argumento. No es necesario, ya que es un método estático, que recibe internamente el ThreadLocal del subproceso actualmente en ejecución. Puede haber como mucho un Looper asociado a cualquier Thread .

Ahora, llamar a new Handler() asociaría el nuevo objeto Handler con el Looper del Thread actual llamando internamente Looper.myLooper() . Puede crear más de un Handler cada uno con su propia devolución de llamada en el mismo subproceso. Todos los manejadores obtendrían sus mensajes de la cola de mensajes del mismo Looper .

No dices nada. De la documentación de Handler :

Cada instancia de Handler se asocia con un solo subproceso y la cola de mensajes del subproceso. Cuando crea un nuevo Handler, está enlazado a la fila / cola de mensajes del subproceso que lo está creando. A partir de ese momento, entregará mensajes y ejecutables a esa cola de mensajes y los ejecutará cuando salgan de la cola de mensajes .

El controlador se vincula automáticamente a la cola de mensajes del subproceso. Sólo implementa la devolución de llamada y el sistema se ocupará de todo, es decir, despachar y procesar los mensajes. En realidad estoy de acuerdo en que, usando dos métodos estáticos como Looper.prepare() y Looper.loop() y automáticamente inferir las cosas, hace que el patrón se siente como la magia negra 🙂

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.