Android MessageQueue and Loop analysis

Source: Internet
Author: User

We first look at the creation of Handlerthread,

publicclass HandlerThread extends Thread {    @Override    publicvoidrun() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }}

Call Looper.prepare () to prepare a looper for the current ready-made

publicstaticvoidprepare() {    prepare(true);}privatestaticvoidprepare(boolean quitAllowed) {    if (sThreadLocal.getnull) {        thrownew RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}

Use sthreadlocal to ensure that each thread has its own Looper object

Finally, inside the Handlerthread Run method, enter the Looper.loop method

 Public Static void Loop() {FinalLooper me = Mylooper ();if(Me = =NULL) {Throw NewRuntimeException ("No Looper; Looper.prepare () wasn ' t called on the This thread. "); }FinalMessageQueue queue = Me.mqueue;//Make sure the identity of this thread is the the local process,    //And keep track of the What, identity token actually is.Binder.clearcallingidentity ();Final LongIdent = Binder.clearcallingidentity (); for(;;) {Message msg = Queue.next ();//might block        if(msg = =NULL) {//No message indicates that the message queue is quitting.            return; }//This must is in a local variable, with case a UI event sets the loggerPrinter logging = me.mlogging;if(Logging! =NULL) {Logging.println (">>>>> dispatching to"+ Msg.target +" "+ Msg.callback +": "+ msg.what); } msg.target.dispatchMessage (msg);if(Logging! =NULL) {Logging.println ("<<<<< finished to"+ Msg.target +" "+ Msg.callback); }//Make sure that during the course of dispatching the        //identity of the thread wasn ' t corrupted.        Final LongNewident = Binder.clearcallingidentity ();if(Ident! = newident) {LOG.WTF (TAG,"Thread identity changed from 0x"+ long.tohexstring (ident) +"to 0x"+ long.tohexstring (newident) +"while dispatching to"+ Msg.target.getClass (). GetName () +" "+ Msg.callback +"what="+ msg.what);    } msg.recycleunchecked (); }}

You can see that this is a dead loop, and each time you take a message out of the MessageQueue and take it out for processing and dispatch.
The role of binder.clearcallingidentity () I guess is used to clear the remote caller's ID, because the remote IPC thread may not have some permissions, after the ID is cleared, you can do some permission operation on behalf of the remote process.

Let's look at the next method of MessageQueue:

Message Next () {//Return hereifThe messageLoophas already quit andbeen disposed.//This can happenifThe application tries to restart a looper after quit//which is  notSupported. Final long ptr = mptr;if(ptr = =0) {return NULL; } int pendingidlehandlercount =-1;//-1Only during first iteration int nextpolltimeoutmillis =0; for(;;) {if(Nextpolltimeoutmillis! =0) {binder.flushpendingcommands ();        } nativepollonce (PTR, nextpolltimeoutmillis); Synchronized ( This) {//Try to retrieve the next message. ReturnifFound.            Final Long now = Systemclock.uptimemillis (); Message prevmsg =NULL; Message msg = mmessages;if(msg! =NULL&& Msg.target = =NULL) {//Stalled bya barrier. Find the next asynchronous messageinchThe queue. Do{prevmsg = msg;                msg = Msg.next; } while(msg! =NULL&&!msg.isasynchronous ()); }if(msg! =NULL) {if(Now < Msg.) when) {//Next message is  notReady. Set a timeout to wake up whenIt isReady. 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(false) LOG.V ("MessageQueue","Returning message:"+ msg);returnMsg }            }Else{//No more messages. Nextpolltimeoutmillis =-1; }//Process the Quit message now, all pending messages has been handled.if(mquitting) {Dispose ();return NULL; }//If First time Idle, ThenGet the number ofIdlers to run.//Idle handles only runifThe queue isEmptyor ifThe first message// inchThe queue (possibly a barrier) isDue to be handledinchThe future.if(Pendingidlehandlercount <0&& (Mmessages = =NULL|| Now < Mmessages. when) {Pendingidlehandlercount = Midlehandlers.size (); }if(Pendingidlehandlercount <=0) {//No idle handlers to run. Loop andWait 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 Thiscode block during the first iteration. for(int i =0; i < Pendingidlehandlercount;            i++) {final Idlehandler idler = mpendingidlehandlers[i]; Mpendingidlehandlers[i] =NULL;//Release the reference to the handler Boolean keep =false;Try{keep = Idler.queueidle (); }Catch(Throwable t) {LOG.WTF ("MessageQueue","Idlehandler threw exception", t); }if(!keep) {Synchronized ( This) {Midlehandlers.remove (idler); }            }        }//Reset the idle handler count to0So we Do  notRun them again. Pendingidlehandlercount =0;//While calling an idle handler, aNewMessage could has been delivered//So go back andLook again forA pending message without waiting. Nextpolltimeoutmillis =0; }}

The function of Nativepollonce (PTR, Nextpolltimeoutmillis) is to invoke the Jni method to perform a poll operation if the current message queue is empty (or empty except for some timed message that is not yet present). This method returns only if the message queue has a new message (or the time-out expires) and continues processing.

At the end of the loop, there is a concept called Idlehandler, which is called when the message queue is not currently available for processing, which means that when the idlehandler is called, the Idlehandler This means that Message Queuing is currently in a state where no messages can be processed, and the app can add Idlehandler using the MessageQueue Addidlehandler method.

Android MessageQueue and Loop analysis

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.