How to create a Looper thread, then send it a message immediately?
Solution 1:
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(); // <- ADDED
worker.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!
Solution 2:
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.