Ejemplo de comunicación con HandlerThread

Quiero configurar un HandlerThread desde el hilo de GUI. Luego, un tiempo después, cuando se hace clic en un botón de la GUI, se ejecuta callHello (), que luego envía un mensaje a un objeto HelloLogger que reside en el hilo que no es GUI y que registra asincrónicamente “Hello World”. He intentado varias cosas, algunas bloquean indefinidamente, algunas nunca reciben el mensaje, etc. El código siguiente es más o menos lo más parecido que tengo, ¿podría alguien modificarlo para que funcione?

public class HandlerThreadExample { private MyHandlerThread mMyHandlerThread; private Looper mLooper; private Handler mHandler; public HandlerThreadExample(){ mMyHandlerThread = new MyHandlerThread(); mMyHandlerThread.start(); mLooper = mMyHandlerThread.getLooper(); } public void callHello() { mHandler.sendEmptyMessage(1); } private class MyHandlerThread extends HandlerThread { private HelloLogger mHelloLogger; private Handler mHandler; public MyHandlerThread() { super("The MyHandlerThread thread", HandlerThread.NORM_PRIORITY); } public void run (){ mHelloLogger = new HelloLogger(); mHandler = new Handler(getLooper()){ public void handleMessage(Message msg){ mHelloLogger.logHello(); } }; super.run(); } } private class HelloLogger { public HelloLogger (){ } public void logHello(){ Log.d("HandlerThreadExample", "Hello World"); } } } 

Mejores ejemplos encontrados:

  • HandlerThread Test
  • ¿Cómo crear un hilo Looper, y luego enviar un mensaje de inmediato?
  • Llamadas asíncronas con Handler
  • HandlerThread vs Executor – ¿Cuándo es uno más apropiado que el otro?
  • El mejor uso de HandlerThread sobre otras clases similares
  • Android HandlerThread
  • Ejemplos de HandlerThread
  • Android: paso de datos entre los hilos principal y de trabajo
  • Java sincronizado
  • Envío de mensajes entre subprocesos utilizando cola de hilo de actividad y clase Handler
  • Introducción a Loopers y Handlers
  • developer.android: especificando el código para ejecutar en un subproceso

Al menos ahora puedo cerrar las malditas tabs

Solución cortesía de la ayuda de pskink

 public class HandlerThreadExample2 { private static int MSG_START_HELLO = 0; private static int MSG_HELLO_COMPLETE = 1; private HandlerThread ht; private Handler mHtHandler; private Handler mUiHandler; private boolean helloReady = false; public HandlerThreadExample2(){ ht = new HandlerThread("The new thread"); ht.start(); Log.d(App.TAG, "UI: handler thread started"); mUiHandler = new Handler(){ public void handleMessage(Message msg){ if (msg.what == MSG_HELLO_COMPLETE){ Log.d(App.TAG, "UI Thread: received notification of sleep completed "); helloReady = true; } } }; mHtHandler = new Handler(ht.getLooper()){ public void handleMessage (Message msg){ if (msg.what == MSG_START_HELLO){ Log.d(App.TAG, "handleMessage " + msg.what + " in " + Thread.currentThread() + " now sleeping"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Log.d(App.TAG, "Woke up, notifying UI thread..."); mUiHandler.sendEmptyMessage(MSG_HELLO_COMPLETE); } } }; } public void sendLongHello(){ if (helloReady){ Log.d(App.TAG, "sending hello " + Thread.currentThread()); mHtHandler.sendEmptyMessage(MSG_START_HELLO); helloReady = false; } else { Log.e(App.TAG, "Cannot do hello yet - not ready"); } } } 

Este es un ejemplo de trabajo:

 HandlerThread ht = new HandlerThread("MySuperAwesomeHandlerThread"); ht.start(); Handler h = new Handler(ht.getLooper()) { public void handleMessage(Message msg) { Log.d(TAG, "handleMessage " + msg.what + " in " + Thread.currentThread()); }; }; for (int i = 0; i < 5; i++) { Log.d(TAG, "sending " + i + " in " + Thread.currentThread()); h.sendEmptyMessageDelayed(i, 3000 + i * 1000); } 

ACTUALIZAR :

Haz dos campos de clase:

 Handler mHtHandler; Handler mUiHandler; 

y prueba esto:

 HandlerThread ht = new HandlerThread("MySuperAwsomeHandlerThread"); ht.start(); Callback callback = new Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == 0) { Log.d(TAG, "got a meaasage in " + Thread.currentThread() + ", now sleeping... "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Log.d(TAG, "woke up, notifying ui thread..."); mUiHandler.sendEmptyMessage(1); } else if (msg.what == 1) { Log.d(TAG, "got a notification in " + Thread.currentThread()); } return false; } }; mHtHandler = new Handler(ht.getLooper(), callback); mUiHandler = new Handler(callback); mHtHandler.sendEmptyMessageDelayed(0, 3000); 

Por supuesto, puedes deshacerte de la interfaz Callback y crear dos Handlers con el método handleMessage reemplazado ...

El problema que está viendo es que su clase externa está usando un campo mHandler privado y también lo hace su HandlerThread. El campo de la clase externa ‘no está inicializado. No necesitas el mHandler interno. La clase externa puede crear un controlador desde el looper que capturas justo después de llamar a start ().