thread handlerthread example android multithreading android-handler android-handlerthread

handlerthread - service handler android



Ejemplo de comunicaciĆ³n con HandlerThread (2)

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:

Al menos ahora puedo cerrar las malditas pestañas

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"); } } }


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 ().


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 ...