How to create a Looper thread, then send it a message immediately?
Eventual solution (minus error checking), thanks to CommonsWare:
class Worker extends HandlerThread { // ... public synchronized void waitUntilReady() { d_handler = new Handler(getLooper(), d_messageHandler); }}
And from the main thread:
Worker worker = new Worker();worker.start();worker.waitUntilReady(); // <- ADDEDworker.handler.sendMessage(...);
This works thanks to the semantics of HandlerThread.getLooper()
which blocks until the looper has been initialized.
Incidentally, this is similar to my solution #1 above, since the HandlerThread
is implemented roughly as follows (gotta love open source):
public void run() { Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Looper.loop();}public Looper getLooper() { synchronized (this) { while (mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper;}
The key difference is that it doesn't check whether the worker thread is running, but that it has actually created a looper; and the way to do so is to store the looper in a private field. Nice!
take a look at the source code of HandlerThread
@Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; }
Basically, if you are extending Thread in worker and implementing your own Looper, then your main thread class should extend worker and set your handler there.
This is my solutions: MainActivity:
//Other Code mCountDownLatch = new CountDownLatch(1); mainApp = this; WorkerThread workerThread = new WorkerThread(mCountDownLatch); workerThread.start(); try { mCountDownLatch.await(); Log.i("MsgToWorkerThread", "Worker Thread is up and running. We can send message to it now..."); } catch (InterruptedException e) { e.printStackTrace(); } Toast.makeText(this, "Trial run...", Toast.LENGTH_LONG).show(); Message msg = workerThread.workerThreadHandler.obtainMessage(); workerThread.workerThreadHandler.sendMessage(msg);
The WorkerThread Class:
public class WorkerThread extends Thread{ public Handler workerThreadHandler; CountDownLatch mLatch; public WorkerThread(CountDownLatch latch){ mLatch = latch; } public void run() { Looper.prepare(); workerThreadHandler = new Handler() { @Override public void handleMessage(Message msg) { Log.i("MsgToWorkerThread", "Message received from UI thread..."); MainActivity.getMainApp().runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.getMainApp().getApplicationContext(), "Message received in worker thread from UI thread", Toast.LENGTH_LONG).show(); //Log.i("MsgToWorkerThread", "Message received from UI thread..."); } }); } }; Log.i("MsgToWorkerThread", "Worker thread ready..."); mLatch.countDown(); Looper.loop(); }}