Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handlers initialized with Looper.getMainLooper() does not respond to message callbacks

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.

like image 332
Some Noob Student Avatar asked Mar 21 '13 02:03

Some Noob Student


People also ask

What is Looper getMainLooper ()?

static Looper. getMainLooper() Returns the application's main looper, which lives in the main thread of the application. MessageQueue. getQueue()

What is Looper message and handler?

Looper is a worker that keeps a thread alive, loops through MessageQueue and sends messages to the corresponding handler to process. Finally Thread gets terminated by calling Looper's quit() method.

What is handler and Looper in android?

Looper is an abstraction over event loop (infinite loop which drains queue with events) and Handler is an abstraction to put/remove events into/from queue with events (which is drained by Looper) and handle these events when they are processed.

When should I use android Looper?

Android Looper is a Java class within the Android user interface that together with the Handler class to process UI events such as button clicks, screen redraws and orientation switches. They may also be used to upload content to an HTTP service, resize images and execute remote requests.


2 Answers

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.

like image 88
devunwired Avatar answered Sep 19 '22 10:09

devunwired


Messages sent to a Handler will only be handled by that Handler, even if it's sharing a Looper.

Buried in the source code for Handler is the line

msg.target = this;

This ensures no other Handler will touch it.

like image 34
j__m Avatar answered Sep 22 '22 10:09

j__m