I am trying to implement Handlers listening on the same Looper from different threads.
Below I have two Handlers, one created in the main thread, another in the child thread, however both are initialized to listen on the Main Looper.
private Handler mMain;
public static final ThreadPoolExecutor tpe =
(ThreadPoolExecutor) Executors.newCachedThreadPool();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMain = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
Log.wtf("", "main:" + msg);
}
};
tpe.execute(new Runnable() {
private Handler tChild = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
Log.wtf("", "child:" + msg);
}
};
@Override
public void run() {
Log.wtf("", "send msg to main looper");
tChild.sendEmptyMessage(100);
}
});
}
But when I send a message like below, only the child handler prints the message. The main handler does not receive the message.
03-20 22:02:26.754: A/(12857): send msg to main looper
03-20 22:02:26.847: A/(12857): child:{ what=100 when=-8ms }
What am I doing wrong? Thank you for reading.
Each Handler
instance controls the Message
target and there is no way to get them to share, so every message or post sent to a Handler
is only executed by that instance.
The Looper
indicates which thread the messages/runnables sent will be executed on. In your code, both Handlers will execute handleMessage()
on the main thread, despite being created on separate threads. That is the real reason you can pass a Looper
instance to a Handler
...if you pass no Looper
, then the Handler
will execute code on the thread in which it was created (which must also be a Looper
thread).
Furthermore, because of this there isn't reason to create multiple Handlers to post data in this manner. A single Handler
is designed to be sent messages from multiple threads, and they are all serialized in a MessageQueue
and executed on the chosen Looper
thread. You can post directly to mMain
from the background thread to execute code on that thread. In this case, passing the Looper
is redundant at that code is already on the main thread.