Handler series (1) -- Handler asynchronous message mechanism (as shown in the figure below), handler asynchronous
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 Yes If the error is returned when a Handler constructor is called, go to the source code of the constructor. * public Handler () {* if (FIND_POTENTIAL_LEAKS) {* final Class <? Extends Handler> 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 I Nside 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 Loo Per. * public static 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. **/** I Nitialize the current thread as a loaliz. ** 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:
<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <TextView android: layout_centerInParent = "true" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "Handler principles"/> </RelativeLayout>
Briefly describe the steps of Handler message transmission mechanism
1. What is the concept of Handler used? 1) execute the scheduled task. You can execute some tasks at the scheduled time and simulate the timer.
2) Inter-thread communication. When an Android Application is started, a main thread is created, and the main thread creates a message queue to process various messages. When creating a sub-thread, you can get the Handler object created in the parent thread in your sub-thread to send messages to the Message Queue of the parent thread. Because Android requires updating the interface in the UI thread, you can update the interface in other threads through this method.
Role Description: 1) Logoff: A thread can generate a logoff object to manage the Message Queue in this thread.
2) Handler: You can construct a Handler object to communicate with logoff, so as to push new messages to the Message Queue, or receive messages sent by logoff from the Message Queue.
3) Message Queue: used to store messages put by threads.
4) thread: the UI thread is usually the main thread, and Android will create a Message Queue for it when starting the program.
Each thread can contain a logoff object and a Message Queue data structure. In your application, you can define the sub-category of Handler to receive messages sent by logoff.
2. Handler Execution Process
Each handler corresponds to a thread. In the child thread, the messages sent by the handler enter the Message Queue, and The logoff will distribute the messages to the Handler for processing.
In android, private Handler mHandler = new Handler () indicates the consciousness and meaning.
Handler is a tool used in android to handle the problem of updating the UI of asynchronous threads.
The UI cannot be updated in the android asynchronous thread. The UI can only be updated in the main thread.
The mhandler here will not be called by you. All you have to do is send messages to handler, and then handler responds to the messages you have sent.
Handler has a message queue, which is arranged according to the order of incoming and outgoing messages. handler will respond to messages in the queue in sequence.
In a word, handler is used when you want to update the UI in an asynchronous thread.