ThreadLocal
Before looking down, you need to know about Java's threadlocal class, you can refer to the blog:
Decryption Threadlocal
Looper, Handler and MessageQueue
Let's analyze the previous code and see what the relationship between Handle, Looper, and MessageQueue is in the handler mechanism.
classWorkerthreadextendsThread {@Override Public voidrun () {Super. Run (); Looper.prepare (); Handler=NewHandler () {@Override Public voidhandlemessage (Message msg) {Super. Handlemessage (msg); LOG.D ("Tttt", "Handlemessage:" +Thread.CurrentThread (). GetName ()); inti =Msg.what; LOG.D ("Tttt", "Received Message object:" +i); } }; Looper.loop (); } }
1. First implement Looper.prepare () ;
To view the source code for Looper, the path is: Sources\android-19\android\os\looper.java
First, several member variables of the Looper class
// Sthreadlocal.get () would return null unless you ' ve called prepare (). Static Final New Threadlocal<looper>(); Private Static Looper Smainlooper; // guarded by Looper.class Final MessageQueue mqueue; Final Thread Mthread;
This indicates that each Looper object corresponds to a message queue (MessageQueue), and also to a thread.
When we call Looper's prepare () method, execute the following code:
public static void prepare () {Prepare ( true Span style= "color: #000000;" >);} private static void Prepare (boolean quitallowed) { if (sthreadlocal.get ()! = null New runtimeexception ("Only one Looper could be created per thread" new Looper ( quitallowed));}
As can be seen from the code above, when Looper.prepare () is executed, the threadlocal get method is called to determine if there is already a key-value pair with the current thread as key, and if it already exists, throws an exception "only one Looper may Be created per thread " . If it does not exist, execute sthreadlocal.set (new Looper (quitallowed)) , create a new Looper object, and deposit it in threadlocal.
Private Looper (boolean quitallowed) { new MessageQueue (quitallowed); = thread.currentthread ();}
As you can see, creating a Looper object creates a new MessageQueue object, assigns the Mqueue property to the Looper object, assigns the current thread to Looper's Mthread property.
2. Next execution
New Handler () { @Override publicvoid handlemessage (Message msg) { Super. Handlemessage (msg); LOG.D ("tttt", "Handlemessage:" + Thread.CurrentThread (). GetName ()); int i = msg.what; LOG.D ("Tttt", "Received Message object:" + i);} };
Instantiate a handler object, execute its Handlemessage method, view handler source, path: Sources\android-19\android\os\hnadler.java
You can see that the handler class has the following member variables
Final MessageQueue mqueue; Final Looper mlooper; Final Callback mcallback; Final Boolean masynchronous; IMessenger Mmessenger;
Find the construction method of its 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; }
The Looper mylooper () method is called to assign a value to Mlooper
Mlooper = Looper.mylooper ();
We view Looper.java
Public Static Looper Mylooper () { return sthreadlocal.get (); }
found that the Looper object that is the key of the current thread is removed from the threadlocal and returned, so when the handler object is created, the handler object gets the Looper object that was created before
if NULL ) { thrownew runtimeexception ( "Can ' t create handler inside thread that have not Called Looper.prepare () "); }
If the Looper object is empty, throw an exception "Can ' t create handler inside thread that have not called looper.prepare ()" informs the user that there is no call to Looper. You cannot create a handler object before Preapre ().
Mqueue = mlooper.mqueue; = callback; = Async;
The mqueue of the Looper object is then given to the mqueue of handler.
In this way, the thread, Handler, Looper, MessageQueue are linked together.
Android Note (33) communication between Android Threads (v) Handle, Looper, and MessageQueue