"Original" Source angle analysis Android message mechanism series (iv) how--MESSAGEQUEUE works

Source: Internet
Author: User

ι Copyright Notice: This article for Bo Master original article, without Bo Master permission not reproduced.

MessageQueue, which consists of 2 operations: insert and read. The read operation is accompanied by a delete operation, and the corresponding methods for inserting and reading are enqueuemessage and next, where the function of Enqueuemessage is to insert a message into the message queue. The role of next is to remove a message from the message queue and remove it from the message queue. Although MessageQueue is called Message Queuing, its internal implementation is not a queue, in fact it is a single-linked list of data structures to maintain the message lists, single-linked list on the insertion and deletion of comparative advantage.

First look at the definition of MessageQueue:

 /**   * Low-level class holding the list of Messages to being dispatched by a * {  @link   Looper  }. Messages is not added directly to a MessageQueue, * but rather through {  @link  Span style= "COLOR: #008000" > Handler} objects associated with the Looper. * * <p>you can retrieve the MessageQueue for the current thread with * {  @link 
     Looper#myqueue () Looper.myqueue ()}.  */ public   Final  class  MessageQueue 

Through the source code we can know, MessageQueue maintained a message list. Messgae is not added directly to the MessageQueue, but is added by handler associated with Looper. In the current thread, you can get the MessageQueue of the current thread by calling the Looper.myqueue () method.

Here's a look at its enqueuemessage insert method:

BooleanEnqueuemessage (Message msg,LongWhen ) {        if(Msg.target = =NULL) {            Throw NewIllegalArgumentException ("Message must has a target.")); }        if(Msg.isinuse ()) {Throw NewIllegalStateException (msg + "This message was already in use.")); }         synchronized( This) {            if(mquitting) {illegalstateexception e=Newillegalstateexception (Msg.target+ "Sending message to a Handler on a dead thread");                LOG.W (TAG, E.getmessage (), E);                Msg.recycle (); return false;            } msg.markinuse (); Msg.when=When ; Message P=mmessages; BooleanNeedwake; if(p = =NULL|| When = = 0 | | When <p.when) {//New Head, Wake up the event queue if blocked.Msg.next =p; Mmessages=msg; Needwake=mblocked; } Else {                //Inserted within the middle of the queue. Usually we don ' t has to wake//Up the event queue unless there are a barrier at the head of the queue//The message is the earliest asynchronous message in the queue.Needwake = mblocked && P.target = =NULL&&msg.isasynchronous ();                Message prev;  for (;;) {prev=p; P=P.next; if(p = =NULL|| When <p.when) { Break; }                    if(Needwake &&p.isasynchronous ()) {Needwake=false; }} Msg.next= P;//Invariant:p = = Prev.nextPrev.next =msg; }             //We can assume mptr! = 0 because mquitting is false.            if(Needwake) {nativewake (mptr); }        }        return true; }

A member property target is defined in the source code of message, and its type is handler. From the source code above Enqueumessage, we can see that when the message does not handle its handler or the message is being processed, it does not enter the MessageQueue normally, which is also very easy to understand. When the thread is in the dead state, the message is reclaimed and no longer enters the corresponding MessageQueue of that thread. Otherwise, everything is fine, Enquemessage executes the single-linked list insert operation and inserts the message into MessageQueue.

Then look at MessageQueue's next read operation:

Message Next () {//Return here if the message loops has already quit and been disposed. //This can happen if the application tries to restart a looper after quit//which is not supported.        Final LongPTR =mptr; if(ptr = = 0) {            return NULL; }         intPendingidlehandlercount =-1;//-1 Only during first iteration        intNextpolltimeoutmillis = 0;  for (;;) {            if(Nextpolltimeoutmillis! = 0) {binder.flushpendingcommands ();             } nativepollonce (PTR, nextpolltimeoutmillis); synchronized( This) {                //Try to retrieve the next message. Return if found.                Final Longnow =Systemclock.uptimemillis (); Message prevmsg=NULL; Message msg=mmessages; if(msg! =NULL&& Msg.target = =NULL) {                    //stalled by a barrier. Find the next asynchronous message in the queue.                     Do{prevmsg=msg; Msg=Msg.next; }  while(msg! =NULL&&!msg.isasynchronous ()); }                if(msg! =NULL) {                    if(Now <msg.when) {//Next message is isn't ready. Set a timeout to wake up when it was ready.Nextpolltimeoutmillis = (int) Math.min (Msg.when-Now , Integer.max_value); } Else {                        //Got a message.mblocked =false; if(Prevmsg! =NULL) {Prevmsg.next=Msg.next; } Else{mmessages=Msg.next; } Msg.next=NULL; if(DEBUG) LOG.V (TAG, "returning message:" +msg);                        Msg.markinuse (); returnmsg; }                } Else {                    //No more messages.                                  }                 //Process The Quit message now, all pending messages has been handled.                if(mquitting) {Dispose (); return NULL; }                 //If First time idle, then get the number of idlers to run. //Idle handles only run if the queue is empty or if the first message//In the queue (possibly a barrier) are due to being handled in the future.                if(Pendingidlehandlercount < 0 && (mmessages = =NULL|| Now <mmessages.when)) {Pendingidlehandlercount=midlehandlers.size (); }                if(Pendingidlehandlercount <= 0) {                    //No idle handlers to run. Loop and wait some more.mblocked =true; Continue; }                 if(Mpendingidlehandlers = =NULL) {mpendingidlehandlers=NewIdlehandler[math.max (Pendingidlehandlercount, 4)]; } mpendingidlehandlers=Midlehandlers.toarray (mpendingidlehandlers); }             //Run the idle handlers. //We only ever reach this code block during the first iteration.             for(inti = 0; i < Pendingidlehandlercount; i++) {                FinalIdlehandler idler =Mpendingidlehandlers[i]; Mpendingidlehandlers[i]=NULL;//release the reference to the handler                 BooleanKeep =false; Try{Keep=Idler.queueidle (); } Catch(Throwable t) {log.wtf (TAG,"Idlehandler threw exception", T); }                 if(!Keep) {                    synchronized( This) {midlehandlers.remove (idler); }                }            }             //Reset The Idle handler count to 0 so we don't run them again.Pendingidlehandlercount = 0; //while calling an idle handler, a new message could has been delivered//So go back and look again for a pending message without waiting.Nextpolltimeoutmillis = 0; }    }

Through the source code we can know that the next method will continue to loop read the message in MessageQueue. If there is no message in the MessageQueue, the next method is temporarily blocked (Nextpolltimeoutmillis =-1). When a message arrives, next continues to read the message, returns it, and removes it from the single-linked list.

"Original" Source angle analysis Android message mechanism series (iv) how--MESSAGEQUEUE works

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.