English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Introducción
Hace unos días vi una pregunta de entrevista: ¿Cuál es la diferencia entre Thread, Handler y HandlerThread? Este tema es interesante, para mucha gente, puede que sean muy familiarizados con Thread y Handler, que se relacionan principalmente con el mecanismo de mensajería de Android (Handler, Message, Looper, MessageQueue), consulte más detalles en “Una vez más, del post de Handler a Runnable, desglosemos el mecanismo de mensajería de Android (y las fugas de memoria de handler)”
Pero ¿para qué se utiliza este HandlerThread? ¿Es un Handler o un Thread? Sabemos que el Handler se utiliza para actualizar UI de manera asincrónica, más detalladamente, para realizar comunicación entre hilos, la comunicación para actualizar UI es entre el hilo secundario y el hilo principal de UI. Entonces, ¿cómo se realiza la comunicación entre hilos secundarios si queremos? Por supuesto, al final, también se hace con Handler+Usamos Thread para completar (no se recomienda, se necesita manejar Looper por sí mismo), Google nos ha ayudado amablemente encapsulando una clase, que es la que mencionamos anteriormente: HandlerThread. (Para escenarios de multi-threading hay otros encapsulamientos similares, como AsyncTask)
Uso
Vamos a ver primero cómo se utiliza HandlerThread:
Primero creamos HandlerThread y ejecutamos start()
private HandlerThread mHandlerThread; ...... mHandlerThread = new HandlerThread("HandlerThread"); handlerThread.start();
Crear Handler, usar mHandlerThread.getLooper() para generar Looper:
final Handler handler = new Handler(mHandlerThread.getLooper()){ @Override public void handleMessage(Message msg) { System.out.println("Recibido el mensaje"); } });
Luego creamos una nueva subproceso para enviar mensajes:
new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000);//Simulación de operaciones de tiempo de ejecución handler.sendEmptyMessage(0); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();
Finalmente, no olvides liberar en onDestroy para evitar fugas de memoria:
@Override protected void onDestroy() { super.onDestroy(); mHandlerThread.quit(); }
El resultado de la ejecución es muy simple, es decir, imprimir la cadena en la consola: Recibido el mensaje
Principio
Durante todo el proceso de uso, no necesitamos preocuparnos por las cosas relacionadas con Handler, solo necesitamos enviar mensajes, procesar mensajes y dejar que el Looper se encargue de manejarlo por sí mismo. Vamos a ver cómo lo hace el código fuente, primero veamos el método constructor:
public class HandlerThread extends Thread {}
What is the difference between HandlerThread and a regular thread?
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } ...... }
The answer is that there is an additional Looper, which is unique to the child thread, used for message retrieval and processing. Let's continue to look at the run method of the HandlerThread thread:
protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper();//Generate Looper notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared();//An empty method, called after the Looper is created, which can be overridden with custom logic Looper.loop();//A deadlock loop, continuously extracting messages from the MessageQueue and delivering them to the Handler for processing mTid = -1; }
It mainly performs some Looper operations, if we use Handler ourselves+If implemented by Thread, this operation also needs to be performed, let's take a look at the getLooper() method:
public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; }
El método es bastante simple, solo se agrega un bloqueo de sincronización. Si ya se ha creado (isAlive() devuelve true) pero mLooper está vacío, se continuará esperando hasta que mLooper se cree con éxito, y finalmente, eche un vistazo al método quit, es digno de mencionar que hay dos:
public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }
quitSafely es para situaciones en las que aún quedan mensajes en la cola de mensajes o mensajes programados para enviar sin procesar. Después de llamar a este método, todos ellos se detendrán.
Resumen
El uso de HandlerThread es bastante simple, pero debemos entender algo: si un hilo debe procesar mensajes, debe tener su propio Looper, no es donde se crea el Handler donde se puede procesar el mensaje.
Si no se utiliza HandlerThread, es necesario llamar manualmente a métodos como Looper.prepare() y Looper.loop().
Aquí está la recopilación de información sobre la relación entre Thread, Handler y HandlerThread, continuaremos complementando información relevante, ¡gracias por el apoyo de todos a este sitio!
Declaración: el contenido de este artículo se obtiene de la red, pertenece al autor original, el contenido se contribuye y carga de manera autónoma por los usuarios de Internet, este sitio no posee los derechos de propiedad, no se ha procesado editorialmente por humanos y no asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de copyright, le invitamos a enviar un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @) para denunciar, y proporcione evidencia relevante. Una vez verificada, este sitio eliminará inmediatamente el contenido sospechoso de infracción.