mensaje de Android mecanismo de manejo de --Handler

1. ¿Por qué usar Handler?

Sub-hilo no puede cambiar el hilo principal de interfaz de usuario, asíncrono mecanismo de procesamiento de mensajes, Handler completado por el cambio de la rosca niño al hilo principal, los datos de solicitud de rosca perfecta solución niño, el hilo principal actualiza los temas de interfaz de usuario

principios básicos 2.Handler

El hilo principal mantiene una noticia columnas (la cola de mensajes), hilo hijo crea un mensaje (mensaje), para enviar el mensaje a la cola de mensajes (cola de mensajes) por el hilo conductor de Handler, el hilo principal donde hay un Round Robin (looper), ciclo continuo para ir a buscar los mensajes, comprobando el mensaje en la columna, no hay mensajes nuevos, una vez encontrado un nuevo mensaje, looper será entregado a Handler objetos, bloqueado de otro modo en un estado de espera, esta vez se hacen llamar el controlador función de devolución de DispatchMessage (mensaje MSG) para actualizar la interfaz de usuario u otras operaciones.
manejador mecanismo principio

3.Handler combinación de análisis de código fuente

3.1 Mensaje

Mensaje: Mensaje
entre la unidad de comunicación de datos hilo puede llevar datos requeridos
para crear objetos: Message.obtain () - piscina mensaje (cadena piscina constante, la piscina está conectado, el grupo de subprocesos)
datos encapsulados
int público lo // identificación ID
int público arg1
public int arg2
obj objeto pública

Crear un mensaje de Message.obtain método ()

  	private static final int MAX_POOL_SIZE = 50;
  	...
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

Mensaje obtenido en la piscina mensaje de los objetos, el número máximo de piscina mensaje 50, si no nuevo un nuevo objeto.

3.2 Procesador Handler

procesador de controlador de mensajes también es responsable de enviar mensajes y trabajos de retirada
enviar un mensaje instantáneo: sendMessage (msg Mensaje)
Enviar un mensaje de retardo: sendMessageDelayed (msg mensaje, mucho tiempo )
procesa el mensaje: handleMessage (msg Mensaje) (devolución de llamada método)
mensaje no ha sido tratada para eliminar: removeMessages (int qué)

método de controlador de sendMessage a los mensajes de envío a la cola de mensajes, se le dará el método de procesamiento final a enqueueMessage

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
 		//把当前Handler对象赋值给msg的成员变量target,保证了谁发送谁处理
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

El método en el objeto Handler se asigna a los miembros msg variables del objetivo, para asegurar que envió a quienes el tratamiento. Por último, dado el método MessageQueue enqueueMessage () para su procesamiento.

3.3 cola de mensajes MessageQueue

Mira MessageQueue el método enqueueMessage () que al final hacer lo

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

Se utiliza para almacenar los mensajes enviados por Handler, que es de un mensaje cuando es ordenado por cola de prioridad. (Cuando se representa el tiempo para ser procesados)

3,4 Looper circulador

Retire Message Queue responsable de hacer circular dentro del mensaje actualmente procesamiento requerido
para ser procesado Handler correspondiente al
procesado, el mensaje a mensaje agrupación de almacenamiento intermedio para una futura reutilización

Luego viene la pregunta? Cuando Looper la noticia?
Looper es cuando se creó?
Mientras MessageQueue frontal no dijo qué hora fue creado?

Primero debemos entender que estalló la razón por la aplicación podría haber sido ejecutado antes de que responder a esta pregunta? El método de entrada donde de nuevo?
La respuesta está en el interior de esta clase ActivityThread y ver lo que todo lo hizo

    public static void main(String[] args) {
        ....
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        ...
        Looper.loop();
        ...
    }

método principal llama Looper.prepareMainLooper (), aspecto ir

public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

preparar (falso) ¿Qué hizo?

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

sThreadLocal para el almacenamiento de datos dentro de la rosca, sThreadLocal.set (nueva Looper (quitAllowed)) creado Looper constructor de objeto mirada ir canto

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

Una vez más hemos creado MessageQueue, es decir, un looper correspondiente a la posición de MessageQueue, se correlacionaron.

Después de crear un looper, sMainLooper = myLooper () lo que hicieron?

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

Esta vez el hilo principal ha sido creado en este Looper.
Volver al método principal y finalmente ejecutado Looper.loop (), cuando este método de hacerlo? Con preguntas fuimos a mirada en ella

    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        ...

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            ...
            try {
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }   
           ...
            msg.recycleUnchecked();
        }
    }

El código es largo, no es necesario mirar el conjunto, para extraer el código de la llave

Looper finales Me = myLooper (); ponerse en frente del hilo de bucle principal creado
para (;;) {
el mensaje MSG = queue.next (); // obtener el mensaje de la cola de mensajes continuamente
IF (MSG == null) {
// . no hay noticias de cuándo salir del bucle de
retorno;
}
...
el try {
// este método se utiliza para distribuir mensajes al tratamiento manipulador, objetivo especificar que lo hizo que se ocupan de
msg.target.dispatchMessage (msg);
}
}

Se trata de un ciclo de muerte, lo que explica por qué la aplicación siempre se puede ejecutar abierta, a menos que salga el programa manualmente, sin mensajes volverá a salir del programa, de lo contrario el mensaje ha sido leído, y fuera mano

proceso de distribución de mensajes 3,5 DispatchMessage

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

Hay tres maneras de lidiar con esto,

  1. handleCallback (msg);
    cuando se crean los mensajes de devolución de llamada, procesada por el mensaje mismo, por ejemplo:
	Handler handler = new Handler();
	handler.post(new Runnable() {
	    @Override
	    public void run() {
	    //UI操作
	    }
	});
  1. mCallback.handleMessage (msg)
    Cuando el Handler ha creado de devolución de llamada (interfaz interna), el proceso de devolución de llamada a sí mismos, por ejemplo:
   Handler.Callback callback = new Handler.Callback() {
       @Override
       public boolean handleMessage(Message msg) {
       		//UI操作
           return false;
       }
   };
   Handler handler = new Handler(callback);
   //子线程发送消息
   handler.sendMessage(msg);
  1. handleMessage (msg) Ejemplo:
     Handler handler = new Handler(){
          @Override
          public void handleMessage(Message msg) {
              //UI操作
          }
      };
	  //子线程发消息
	  handler.sendMessage(message);

Y después se une a esquemáticas
principio manejador
dejan abiertas varias cuestiones de referencia?
¿Cuál es la diferencia entre el método de correos y un método sendMessage 1.Handler es?
2. Handler puede crear en el hilo hijo? Cómo crear?
3. Un hilo puede tener múltiples Handler, Looper, MessegeQueue ella?

Publicado 28 artículos originales · ganado elogios 1 · visitas 527

Supongo que te gusta

Origin blog.csdn.net/qq_40575302/article/details/104535997
Recomendado
Clasificación