Handler detail series (1) -- Detailed description of Handler asynchronous message mechanism (see figure)

Source: Internet
Author: User

Handler detail series (1) -- Detailed description of Handler asynchronous message mechanism (see figure)
MainActivity is as follows:

Package cc.cn; import android. OS. bundle; import android. OS. handler; import android. OS. logoff; import android. OS. message; import android. util. log; import android. app. activity;/*** Demo Description: * Android asynchronous message mechanism analysis (see figure) ** ===================================================== =============================** introduction of the problem: * When Handler handler = new Handler () is directly called in a child thread, the following error occurs: * Can't create handler inside thread that has not called logoff. prepare (). * Since the error is reported when the Handler constructor is called, let's look at the source code of the constructor. * public Handler () {* if (FIND_POTENTIAL_LEAKS) {* final Class
 Klass = getClass (); * if (klass. isAnonymousClass () | klass. isMemberClass () | klass. isLocalClass () * & (klass. getModifiers () & Modifier. STATIC) = 0) {* Log. w (TAG, "The following Handler class shoshould be * static or leaks might occur:" + klass. getCanonicalName (); *} ** mlogoff = logoff. myLooper (); * if (mloexception = null) {* throw new RuntimeException (* "Can't create handler inside thread that Has not called logoff. prepare () "); *} * mQueue = mloue. mQueue; * mCallback = null; *} ** from the above Code mloue = logoff. mylogoff () Can be seen that when mloiter = null, the error * Can't create handler inside thread that has not called logoff will be reported. prepare (). * ** continue reading The logoff. source code of mylogoff. ** Return the loginobject associated with the current thread. ** Returns null if the calling thread is not associated with a logoff. * public stat Ic logoff mylogoff () {* return sThreadLocal. get (); *} * See the two lines in the source code: * return The logoff associated with the current thread. * If the current thread does not have a logoff associated with it, null is returned. ** check whether the preceding error Can't create handler inside thread that has not called loled. prepare (). * We are prompted to call logoff. prepare (). * write this in the Child thread: * logoff. prepare (); * Handler handler = new Handler (); * The error message disappears. ** since logoff is called. prepare () can eliminate this error. * Let's take a look at logoff. prepare () source code. **/** Initialize the curr Ent thread as a loose. ** This gives you a chance to create handlers that then reference ** this logoff, before actually starting the loop. be sure to call ** {@ link # loop ()} after calling this method, and end it by calling ** {@ link # quit ()}. * public static void prepare () {* if (sThreadLocal. get ()! = Null) {* throw new RuntimeException ("Only one Looper may be created per thread"); *} * sThreadLocal. set (new LOE (); *} * 1 from the annotation document, we can see the role of the prepare () method: * use A loe to initialize the current thread. * 2 you must call the prepare () method before calling the loop () method. * 3 Note the exception message of this method: * Only one Looper may be created per thread * Each thread has Only one Looper !!!! ** Code in this method: sThreadLocal. set (new loue (); * Looper constructor: * private Looper () {* mQueue = new MessageQueue (); * mRun = true; * mThread = Thread. currentThread (); *} * you can see that a logoff is saved for sThreadLocal. * therefore, sThreadLocal is called in the above mylogoff () method. get () is no longer empty. * ** at this point, Handler should be used in a child Thread: * class LooperThread extends Thread {* public Handler mHandler; ** public void run () {* loler. prepare (); ** mHand Ler = new Handler () {* public void handleMessage (Message msg) {* // process incoming messages here *}; ** logoff. loop (); *} * This Code is also recommended by Google. * ** logoff is not called when Handler is used in the UI thread of MainActivity. prepare (); * Why? * Because the UI thread is the main thread, the system has automatically called logoff for us. prepare () method. * I will not go into details here. * ** the preceding sections discuss the use of threads and loopers. The following sections describe the message sending and processing processes. * The most common method: * handler. sendMessage (message); * So how does handleMessage (Message msg) obtain the sent message ??? * Handler can send messages in several methods, but several methods except sendMessageAtFrontOfQueue (Message msg) * will eventually call the sendMessageAtTime (Message msg, long uptimeMillis) method: ** public boolean sendMessageAtTime (Message msg, long uptimeMillis) {* boolean sent = false; * MessageQueue queue = mQueue; * if (queue! = Null) {* msg.tar get = this; * sent = queue. enqueueMessage (msg, uptimeMillis); *} * else {* RuntimeException e = new RuntimeException (* this + "sendMessageAtTime () called with no mQueue"); * Log. w ("logoff", e. getMessage (), e); *} * return sent; *} ** there are two important codes in this method: * 1 msg.tar get = this; * set target for msg. * this here is of course the current Handler object! * 2 sent = queue. enqueueMessage (msg, uptimeMillis); * put the message into the message queue. * The queue (mQueue) Here is the mQueue In The logoff constructor. * The enqueueMessage (msg, uptimeMillis) method has a queue. * messages with the shortest trigger time are placed at the top of the queue, and messages with the longest trigger time are placed at the end of the queue. * if you call the sendMessageAtFrontOfQueue () method to send a message, it will call the enqueueMessage (msg, uptimeMillis) * to enable the message to queue only when the delay time is 0, that is, it will be inserted into the queue header. * ** this is the queue operation for messages. How can a message be sent out of the queue? * It depends on the logoff loop () method * public static final void loop () {* lodomainme = myloath(); * MessageQueue queue = me. mQueue; * while (true) {* Message msg = queue. next (); // might block * if (msg! = Null) {* if (msg.tar get = null) {* return; *} * if (me. mLogging! = Null) me. mLogging. println (* ">>>>> Dispatching to" + msg.tar get + "" + msg. callback + ":" + msg. what); * msg.tar get. dispatchMessage (msg); * if (me. mLogging! = Null) me. mLogging. println (* "<Finished to" + msg.tar get + "" + msg. callback); * msg. recycle (); *} * In this method is an endless loop while (true), that is, logoff is always polling the Message Queue (MessageQueue) * There are two important codes in this method: * 1 Message msg = queue. next (); * queue. the output column of the next () message queue. * 2 msg.tar get. dispatchMessage (msg); * call the dispatchMessage () method of the target in msg. * What is target? * See sendMessageAtTime (Message msg, long uptimeMillis). We can see that * target is Handler !!!! The dispatchMessage method of Handler is called back here, so the message is sent to the corresponding Handler. * Next, let's take a look at the Handler's dispatchMessage (Message msg) method: ** public void dispatchMessage (Message msg) {* // 1 message callback * if (msg. callback! = Null) {* handleCallback (msg); *} else {* // 2 handler's callback * if (mCallback! = Null) {* if (mCallback. handleMessage (msg) {* return; *} * // handleMessage () * handleMessage (msg) of 3 Handler; **} ** the CallBack involved is: * public interface Callback {* public boolean handleMessage (Message msg); *} * One of Handler's constructor methods is: * Handler handler = new Handler (callback ); * In dispatchMessage (Message msg), CallBack is involved. * In most cases, the callBack of message and Handler is empty. * therefore, dispatchMessage (Messa Ge msg) method: * this is back to what we are most familiar. * *** ============================================== ===============================** Android asynchronous message mechanism mainly involves: * Thread Handler low.messagequeue * their relationships are as follows: * 1 logoff. prepare (); * 1.1 generates the corresponding logoff for the current thread. * A loose contains three variables: * mQueue ----> MessageQueue * mRun ------> true * mThread ---> the current thread * 1.2 saves the loose to ThreadLocal. * The main purpose of using ThreadLocal to store the logoff corresponding to a thread is to ensure that * Each thread has only one unique logoff. ** Loop Code of the association between er and Its thread: * 1.3 logoff. mylogoff () * gets the logoff * 1.4 logoff associated with the current thread. mylogoff (). getThread () * Get the Thread associated with logoff ** 2 Handler handler = new Handler () * use logoff in step 1. prepare () implements the association between logoff and thread. * Next, let's look at the relationship between Handler and logoff. * pay attention to the Code in the preceding Handler constructor: * mLooper = Looper. mylogoff (); * in this way, the logoff associated with the thread is obtained. * mQueue = mloue. mQueue; * Get the MessageQueue Message Queue (MessageQueue) mQueue associated with the thread * as shown in the Handler construction method, Han Association between dler and logoff. ** conclusion: * (1) logoff. prepare (); * implements the association between logoff and the thread to which it belongs * (2) Handler handler = new Handler () * implements the association between Handler and logoff. * (3) one thread can have multiple Handler, but only one logoff *** ============================ =, here we will summarize the process of * Android asynchronous message mechanism: ** 1 logoff. prepare (); * implement logoff and its associated thread. * logoff contains three variables: * mQueue ----> MessageQueue * mRu N ------> true * mThread ---> the current thread * has a MessageQueue in each logoff after this method is executed. * All messages sent by Handler are stored in the MessageQueue. * 2 Handler handler = new Handler (); * associates Handler with logoff. * 3 logoff. loop (); * start to poll the Message Queue (MessageQueue) and keep polling. * process each message in the queue. of course, the queue is empty at the beginning. * 4 mHandler. sendMessage (message) sends a message to the message queue. * For detailed procedures, see the preceding description. * 5 logoff in step 3. isn't loop () always polling the message queue? * When a Message is out of the queue, find the target (actually a Handler) callback of the Message * its dispatchMessage (Message msg) method; in this method, handleMessage (Message msg) that we are very familiar with * is called ). ** the above is the detailed process of Android asynchronous message mechanism. * Simply put, you can say: * Handler ------> send messages and process messages * login-------> Use MessageQueue to save messages. use the loop () method to keep polling the message queue. * send the message to the appropriate Handler when it leaves the queue. ** for the above process analysis, see the flowchart. ** ===================================================== =========================== * References: * 1 http://androidxref.com/4.0.4/ * 2 http://blog.csdn.net/guolin_blog/article/details/9991569 * 3 http://blog.csdn.net/aaa2832/article/details/7773220 * 4 http://blog.csdn.net/lilu_leo/article/details/8145320 * 5 http://blog.csdn.net/oney139/article/details/7922742 * 6 http://www.cnblogs.com/cqcmdwym/archive/2013/05/12/3074138.html * Thank you very much */public class MainActivity extends Activity {private Thread mThread; private Handler mHandler; private final String TAG = "Handler"; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); testHandler ();} private void testHandler () {mThread = new Thread (new Runnable () {@ Overridepublic void run () {loid. prepare (); mHandler = new Handler () {@ Overridepublic void handleMessage (Message msg) {super. handleMessage (msg); if (msg. what == 123) {Log. I (TAG, "received message msg. arg1 = "+ msg. arg1) ;}}; Message message = new Message (); message. what = 123; message. arg1 = 456; mHandler. sendMessage (message); logoff. loop () ;}}); mThread. start ();}}


The figure is as follows:


Main. xml is as follows:

     
  
 


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.