Android 2.1: Muliple Handlers in a Single Activity

2020-03-27 09:48发布

问题:

I've more than one Handlers in an Activity. I create all the handlers in the onCreate() of the main activity. My understanding is the handleMessage() method of each handler will never be called at the same time because all messages are put in the same queue (the Activity thread MessageQueue). Therefore, they will be executed in the order in which are put into the Queue. They will also be executed in the main activity thread. Is this correct ?

 public void onCreate() {

this.handler1 = new Handler() {
@Override
public void handleMessage(Message msg) {

                            //operation 1 : some operation with instanceVariable1
super.handleMessage(msg);
}
};

this.handler2 = new Handler() {

@Override
public void handleMessage(Message msg) {
                            //Operation 2: some operation with instanceVariable1
super.handleMessage(msg);
}

};

this.handler3 = new Handler() {
@Override
public void handleMessage(Message msg) {
                            //Operation 3: some operation with instanceVariable1
super.handleMessage(msg);

}
};
}

回答1:

From the docs "When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue."

So you're right, they will run in the order that you queue them on the UI thread (since you are going to create them in onCreate).



回答2:

One message per time, and per thread, and per handler.

  1. Every new Handler(...) instance is bound, explicitly or implicitly, to Looper instance, and only once.
  2. Looper instance, is already created somewhere with Looper.prepare() call //usually obtained by Activity.getMainLooper() or Looper.myLooper()
  3. Looper.prepare() uses ThreadLocal variable sThreadLocal (static field) to have one Looper instance per thread. ( It works same like hashMap.put(Thread.getCurrent(), new Looper()) )
  4. every looper has its own private MessageQueue
  5. every Looper instance has its main method loop()

    loop(){
        while(true){
            Message msg = messageQueue.next();
            msg.target.dispatchMessage(msg);
        }
    }
    
  6. every message have a (Handler) target is set, and exception is thrown(within MessageQueue.enqueueMessage()) if it does not.

  7. since Handler cannot be bound to several Loopers is does so every handler receives only one message at time and only with msg.target==handler

so sendMessage() or postMessage() works something like this:

    handler.post(Message msg){
        Looper.sThreadLocal.get(Thread.getCurrent()).messageQueue.push(msg);
    }

so call stack , while handle message, should look something like this:

Looper.myLooper()-> Thread.getCurrent()-> Looper-> MessageQueue.next()-> Message-> Message.target-> Handler-> dispatchMessage()-> handleMessage()