Looper Preparation
When handler is instantiated, it gets looper from the current thread, obtaining MessageQueue for sending messages. Then, the thread is not born with a Looper object, it needs to call the static method Looper.prepare () in the threads execution, and eventually calls to the following static method:
Private Static void Prepare (boolean quitallowed) { ifnull) { ThrowNew runtimeexception ("Only one Looper could be created per thread"); } Sthreadlocal.set (new Looper (quitallowed));}
The static variable sthreadlocal is an instance of the generic class threadlocal<looper> that holds the mapping between the thread and its Looper: Sthreadlocal is itself a key, Puts the Looper instance into the Threadlocalmap of the current thread (the field named Threadlocals,threadlocalmap is implemented by a hash table). Since any thread holds looper with sthreadlocal as key, there can be at most one looper for any thread.
Public voidset (T value) {Thread T=Thread.CurrentThread (); Threadlocalmap Map=Getmap (t); if(Map! =NULL) Map.set ( This, value); ElseCreatemap (t, value);} PublicT Get () {Thread T=Thread.CurrentThread (); Threadlocalmap Map=Getmap (t); if(Map! =NULL) {threadlocalmap.entry e= Map.getentry ( This); if(E! =NULL) return(T) E.value; } returnsetinitialvalue ();}Looper cycle
After the preparation is complete, enter the Looper loop by calling Looper.loop (). Looper in the cycle of death, constantly from the MessageQueue to get messages, to handler dispatchmessage for processing. The key code for the loop function is the area marked with a yellow background:
1 Public Static voidLoop () {2 FinalLooper me =Mylooper ();3 if(Me = =NULL) {4 Throw NewRuntimeException ("No Looper; Looper.prepare () wasn ' t called on the This thread. ");5 }6 FinalMessageQueue queue =Me.mqueue;7 8 //Make sure the identity of the the the the The local process,9 //And keep track of the What, identity token actually is.Ten binder.clearcallingidentity (); One Final LongIdent =binder.clearcallingidentity (); A - For (;;) { - Message msg = Queue.next (); // might block the 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 logger + FinalPrinter logging =me.mlogging; A if(Logging! =NULL) { atLogging.println (">>>>> dispatching to" + Msg.target + "" + -Msg.callback + ":" +msg.what); - } - - Final LongTracetag =Me.mtracetag; - if(Tracetag! = 0 &&trace.istagenabled (Tracetag)) { in Trace.tracebegin (Tracetag, Msg.target.getTraceName (msg)); - } to Try { + msg.target.dispatchMessage (msg); -}finally { the if(Tracetag! = 0) { * trace.traceend (tracetag); $ }Panax Notoginseng } - the if(Logging! =NULL) { +Logging.println ("<<<<< finished to" + Msg.target + "" +msg.callback); A } the + //Make sure that during the course of dispatching the - //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" the+ long.tohexstring (newident) + "while dispatching to" -+ Msg.target.getClass (). GetName () + ""Wuyi+ Msg.callback + "what=" +msg.what); the } - Wu msg.recycleunchecked (); - } About}
After each message is processed, it is automatically reclaimed and put back in the message pool.
Looper exit
Exit the Looper loop by calling quit or quitsafely. The bottom layer is the QUIT function implementation that calls MessageQueue:
1 voidQuitBooleansafe) {2 if(!mquitallowed) {3 Throw NewIllegalStateException ("Main thread not allowed to quit."));4 }5 6 synchronized( This) {7 if(mquitting) {8 return;9 }TenMquitting =true; One A if(safe) { - removeallfuturemessageslocked (); -}Else { the removeallmessageslocked (); - } - - //We can assume mptr! = 0 because mquitting was previously false. + Nativewake (mptr); - } +}
Quit calls Removeallmessagelocked, which immediately removes all message;quitsafely calls removeallfuturemessagelocked that have not been processed in MessageQueue. This function only removes the Message (that is, Message.when > Now) that executes at the current moment.
Android Source Learning (2) Handler's Looper