Handler: Binds to a thread, a thread can have multiple handler
Looper: The thread and Looper are one by one corresponding, so looper cannot be called two times otherwise it throws an exception
Messge:handler using message to carry messages
Messagqueue: Used for status message, one looper for a message queue
How to determine if a message queue corresponds to a handler, gets the holder of a message queue in SendMessage Looper
Two ways to Looper: Prepare () and loop ()
1.
Public Static Final void prepare () { ifnull) { thrownew runtimeexception ("Looper may created per thread"); } Sthreadlocal.set (new Looper (true));
Set a Looper instance for the current thread
2.
Private Looper (boolean quitallowed) { new MessageQueue (quitallowed); true ; = thread.currentthread ();}
Create a message queue for this looper (in the constructor) and return the current thread
3.
Public Static voidLoop () {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 the the the 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//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" + Lon G.tohexstring (newident) + "while dispatching to" + Msg.target.getClass (). GetName () + "" + Msg.callback + "what=" +msg.what); } msg.recycle (); }}
Public Static Looper Mylooper () { return sthreadlocal.get (); }
The message queue is taken directly from the Looper instance, and then each message is looped (into an infinite loop), which is then distributed through the handler of the messages.
Msg.target.dispatchMessage (msg); The target in the handler is
Summarize the main function of Looper
1) binds to the current thread, guaranteeing that a thread will only have one looper instance, while a Looper instance has only one MessageQueue.
2) Loop () method, constantly from the MessageQueue to fetch messages, to the message of the target property of the DispatchMessage to handle.
Handler
PublicHandler () { This(NULL,false);} PublicHandler (Callback Callback,Booleanasync) { if(find_potential_leaks) {Finalclass<?extendsHandler> Klass =getclass (); if((Klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) &&(Klass.getmodifiers ()& modifier.static) = = 0) {LOG.W (TAG,"The following Handler class should be static or leaks might occur:" +klass.getcanonicalname ()); }} mlooper=Looper.mylooper (); if(Mlooper = =NULL) { Throw NewRuntimeException ("Can ' t create handler inside thread that have not called looper.prepare ()"); } mqueue=Mlooper.mqueue; Mcallback=callback; Masynchronous=Async; }
Handler bound to Looper, because a looper to a message queue, so that the handler is bound to this looper, but also bound to this thread.
Handler.sendmessgae () is used to say that a message is added to the queue of messages: DispatchMessage is used for distribution (as described above looper)
public void DispatchMessage (Message msg) { if (msg.c Allback! = null else { if (mcallback! = null ) { if re Turn ; }} handlemessage (msg); } }
Public void handlemessage (Message msg) { }
Handlemessage is now an empty function that requires our subsequent replication
Steps:
1.first Looper.prepare () saves an looper instance in this thread, and then holds a MessageQueue object in the instance, because Looper.prepare () can only be called once in a thread. So MessageQueue will only exist in one thread. 2. Looper.loop () causes the current thread to enter an infinite loop, which reads the message from the MessageQueue instance and then callbacks the Msg.target.dispatchMessage (msg) method. 3, Handler the construction method, will first get the current thread saved Looper instance, and Looper instance in the MessageQueue want to associate. 4, Handler SendMessage method, will give the target of MSG to handler itself, and then add MessageQueue. 5. When constructing handler instances, we override the Handlemessage method, which is the method that Msg.target.dispatchMessage (msg) eventually calls. 6, handler can also exist in the sub-thread, why we generally see in the main thread? Because it is generally an unsafe operation for UI space updates, handler is placed in the main thread, and if there is no such business, you can certainly use handler
The relationship between Android handler, Looper, and message