Android: complaints between Handler, logoff, and MessageQueue in asynchronous processing (3

Source: Internet
Author: User
Tags sendmsg

Android: complaints between Handler, logoff, and MessageQueue in asynchronous processing (3
(Preface) If you do not know what Handler is in Android before reading this article, I suggest you first read the first blog post "Android: handler + Thread application of asynchronous processing (1); we all know that the UI interface cannot be directly updated in the Child Thread in the Android system, therefore, we usually use Handler + Thread or AsyncTask to update the UI. Handler + Thread is actually a set of mechanisms by which the subthread transmits messages to the UI main Thread and notifies the UI main Thread to update the interface. Sometimes the interviewer prefers to test your Handler mechanism, so it is quite necessary to study the communication mechanism in depth based on the source code. If you can despise the interviewer, haha o (Clerk □clerk) o .. An overview of Google's messaging mechanism is designed with reference to windows. We don't care about patent litigation between uncle and uncle. Generally, threads use logoff to establish their own Message loops and lock a FIFO Message Queue MessageQueue. Handler uses logoff to achieve Message (Message) Access in MessageQueue. Each Hanlder automatically or manually binds a logoff to indirectly send a Message to a MessageQueue during instantiation. Therefore, Handler also encapsulates the interface for sending and receiving messages. This is an example of getting started. It's boring to look at the text. It's obscure and difficult to understand. Remember that it's another big problem. Let's take a look at the example here. So I wrote an example here to send messages to the subthread and display the output. I want to explain it to the subthread. The main code is as follows: copy the public class MainActivity extends ActionBarActivity {private Handler handler; private Button btn; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); btn = (Button) findViewById (R. id. sendmsg); new HandlerThread (). start (); // promoter thread btn. setOnClickListener (new OnClickListener () {@ Override public void on Click (View v) {handler. sendEmptyMessage (0); // send a message to the subthread});} class HandlerThread extends Thread {@ Override public void run () {// start to establish a message loop logoff. prepare (); // initialize loveshandler = new handler () {// by default, loves@override public void handleMessage (Message msg) {switch (msg. what) {case 0: Toast. makeText (MainActivity. this, "The subthread receives the message", Toast. LENGTH_SHORT ). show () ;}}; logoff. loop (); // start the message loop} copy the code Layout File: copy the Code <LinearLayout 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" android: orientation = "vertical"> <Button android: id = "@ + id/sendmsg" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "blow a gun to the subthread! "/> </LinearLayout> to copy the code, you only need to click the button to send the code successfully ..... Let me briefly talk about the process of sending a message: 1. Start a subthread and initialize a logoff in the subthread. 2. Handler is instantiated in HandlerThread, and Handler is automatically bound to the Logoff of the current thread. 3. Rewrite the Message Processing Method in Handler. 4. Execute logoff. loop () to start the message loop, and the sub-thread enters the waiting message status. Of course, it is easy to understand the case after an example. We will explore the establishment of a message loop, the principles of message distribution and processing by combing the preceding message sending process and the source code. 1. for Logoff initialization, go to logoff to view the source code: copy the public static void prepare () {prepare (true);} private static void prepare (boolean quitAllowed) {if (sThreadLocal. get ()! = Null) {throw new RuntimeException ("Only one logoff may be created per thread");} sThreadLocal. set (new logoff (quitAllowed);} when we call the logoff prepare static method, we find that this thread creates a logoff instance, assign the value to the local variable of the sThreadLocal thread. Of course, we can be sure that the sThreadLocal is private to the current thread. Next we will look at the logoff constructor. Private loue (boolean quitAllowed) {mQueue = new MessageQueue (quitAllowed); mThread = Thread. currentThread () ;} I believe everyone's eyes are all bright, right ?! In logoff (), A Message Queue (MessageQueue) is instantiated )! As we wish to bind it to the mQueue local variable, here we can draw a conclusion: Call loue. the prepare () thread creates a message loop object,! The message loop event has not yet started. 2. instantiate Handler and bind the Logoff of the current thread. Let's look at the source code of Handler -- Handler's constructor. Copy the code public Handler () {this (null, false );} public Handler (Callback callback, boolean async) {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 shocould be static or leaks might occur:" + klass. getCanonicalName () ;}} mLooper = Looper. myLooper (); if (mloexception = null) {throw new RuntimeException ("Can't create handler inside thread t Hat has not called logoff. prepare () ");} mQueue = mloue. mQueue; mCallback = callback; mAsynchronous = async;} copy the Code. In the code, we call the handler (Callback callback, boolean async) method through Handler = new Handler; we found that mlogoff = logoff. myloue () binds the Looper in the thread to the Handler and uses mQueue = mloue. mQueue obtains the thread message queue. I can also put it another way: Handler has been bound to the Message Queue of the thread that created this Handler object, so we can start to do bad things .... 3. override handleMessage () method of Handler public void handleMessage (Message msg) {}. There is nothing to say about it. It's just an empty method. It provides our override entry function. 4. It is still the above idea to start the message loop through logoff. loop (). Let's go to loop () and check whether there will always be gains .. Copy the public static void loop () {final Looper me = myLooper (); if (me = null) {throw new RuntimeException ("No lotime; loal. prepare () wasn' t called on this thread. ");} final MessageQueue queue = me. mQueue; Binder. clearCallingIdentity (); final long ident = Binder. clearCallingIdentity (); for (;) {Message msg = queue. next (); // might block if (msg = null) {return;} Printer logging = me. mLoggi Ng; if (logging! = Null) {logging. println (">>>>> Dispatching to" + msg.tar get + "" + msg. callback + ":" + msg. what);} msg.tar get. dispatchMessage (msg); if (logging! = Null) {logging. println ("<Finished to" + msg.tar get + "" + msg. callback);} final long newIdent = Binder. clearCallingIdentity (); if (ident! = NewIdent) {Log. wtf (TAG, "Thread identity changed from 0x" + Long. toHexString (ident) + "to 0x" + Long. toHexString (newIdent) + "while dispatching to" + msg.tar get. getClass (). getName () + "" + msg. callback + "what =" + msg. what);} msg. recycle () ;}} copies the code in the static method of loop (). We can notice the for (;) method. This is a dead-end loop, therefore, we call it a "message loop", which is a bit of an image. In the message loop, the queue. next () is called to obtain the messages waiting for processing in the queue and assign them to the msg variable. next, you can determine if msg is used! = If this parameter is set to null, start message and split message is enabled. msg.tar get. dispatchMessage (msg) is also executed ). After the split message ends, the message will be recycled, as shown in msg. recycle. Msg.tar get is a handler object, indicating the handler object that needs to process the Message. So let's go back to Handler and check out the dispatchMessage () method: copy the public void dispatchMessage (Message msg) code) {if (msg. callback! = Null) {handleCallback (msg);} else {if (mCallback! = Null) {if (mCallback. handleMessage (msg) {return ;}} handleMessage (msg) ;}copy the code. I wonder if you have found handleMessage () at a glance, isn't that the method we used to rewrite Handler in step 3. When msg. callback! = Null and mCallback! = If it is null, handleMessage (msg) will be called to process messages sent by other threads. We will overwrite this method to implement our specific message processing process; this is all the content of the Handler message processing mechanism. Make a summary and read the full text. We can know that the core of the message loop mechanism is logoff, because logoff holds the MessageQueue object and can be set as a local variable by a thread, we can think that this thread has a message queue through logoff. Handler is used to encapsulate the methods for sending and processing messages. In the online communication, the thread can send messages to the thread that creates Handler through Handler, put the message into the message queue of the message receiving thread through logoff, wait for Logoff to retrieve the message and finally give it to Handler to process the specific message. In other words, we will find that it is not necessary to instantiate a Handler in the Activity. prepare () to initialize a logoff and logoff. loop () to start the message loop, because the Activity has initialized logoff and established a message loop during the construction process. For more information, see ActivityThread. code in java: copy the public final class ActivityThread {public static final void main (String [] args ){...... logoff. preparemainlogoff ();...... activityThread thread = new ActivityThread (); thread. attach (false );...... logoff. loop ();...... thread. detach ();... ...}} When the Android application process starts, it loads the ActivityThread class in the process and runs the main function of the class, the message loop process of the application is implemented in this main function. If you want to learn more, we suggest you study the Activity startup mechanism.

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.