Android asynchronous processing three: Handler+looper+messagequeue in-depth explanation

Source: Internet
Author: User

In the Android asynchronous processing one: using Thread+handler to implement non-UI thread update UI interface, we talked about using Thread+handler to implement the interface update, in fact, the non-UI thread sends the message to the UI thread, notifies the UI thread to update the interface. , this article will learn more about the implementation of communication between Android threads.

Overview : Android uses messaging mechanisms to communicate between threads, threads create their own message loops through Looper, MessageQueue is a FIFO message queue, Looper is responsible for extracting messages from MessageQueue. and distributes to the message specifies the target handler object. The handler object binds to the thread's local variable looper, encapsulating the interface that sends the message and processes the message.

Example : Before we introduce the principle, let's introduce an example of the Android thread communication, which is to send the message "Hello" to another thread named "Customthread" from the main thread after the click button.

Code download

Looperthreadactivity.java

 PackageCom.zhuozhuo;Importandroid.app.Activity;ImportAndroid.os.Bundle;ImportAndroid.os.Handler;ImportAndroid.os.Looper;ImportAndroid.os.Message;ImportAndroid.util.Log;ImportAndroid.view.View;ImportAndroid.view.View.OnClickListener; Public classLooperthreadactivityextendsactivity{/**Called when the activity is first created.*/        Private Final intMsg_hello = 0; PrivateHandler Mhandler; @Override Public voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate);        Setcontentview (R.layout.main); NewCustomthread (). Start ();//To Create and start a Customthread instanceFindviewbyid (R.ID.SEND_BTN). Setonclicklistener (NewOnclicklistener () {@Override Public voidOnClick (View v) {//send a message when you click the interfaceString str = "Hello"; LOG.D ("Test", "Mainthread is ready to send msg:" +str); Mhandler.obtainmessage (Msg_hello, str). Sendtotarget ();//sending a message to a Customthread instance                            }        }); }                        classCustomthreadextendsThread {@Override Public voidrun () {//steps to establish a message loopLooper.prepare ();//1. Initialize LooperMhandler =NewHandler () {//2. Binding handler to Customthread instance Looper object                 Public voidHandlemessage (Message msg) {//3. Define methods for handling messages                    Switch(msg.what) { CaseMSG_HELLO:LOG.D ("Test", "Customthread receive msg:" +(String) msg.obj);            }                }            }; Looper.loop ();//4. Start the message loop        }    }}

Main.xml

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "    android:orientation=" vertical "    android:layout_width=" Fill_parent "     Android:layout_height= "Fill_parent"    ><TextView      android:layout_width= "Fill_parent"      android:layout_height= "Wrap_content"     android:text= "@string/hello"    /> <button android:text= "Send Message" android:id= "@+id/send_btn" android:layout_width= "Wrap_content" Android:layout_ height= "Wrap_content" ></Button></LinearLayout>

Log Print Results:

Principle:

We see that there are four steps to establishing a message loop for a thread:

1. Initialize Looper

2. Binding handler to Customthread instance Looper object

3. Define methods for handling messages

4. Start the message loop

Let's take this example as a clue and dive into the Android source code to show how the Android framework builds the message loop and distributes the message.

1. Initialize Looper:Looper.prepare ()

Looper.java

 private  static  final  ThreadLocal sthreadlocal = new   ThreadLocal ();  public  static  final  void   prepare () { if  (sthreadlocal.get ()! = null   throw  new  runtimeexception ("Only one Looper could be created per thread"  new   Looper ());} 

When a thread calls Looper's static method prepare (), the thread creates a new Looper object and puts it into the thread's local variables, which are not shared with other threads (about threadlocal). Let's take a look at the constructor of Looper ():

Looper.java

Final MessageQueue Mqueue; Private Looper () {        new  MessageQueue ();         true ;         = Thread.CurrentThread ();    }

You can see that in the constructor of Looper, a Message Queuing object Mqueue is created, and Looper is called at this time. The thread of the prepare () establishes a message loop object (the message loop has not yet started).

2. Binding Handler to Customthread instance Looper object: mhandler= new Handler ()

Handler.java

FinalMessageQueue Mqueue;FinalLooper Mlooper; PublicHandler () {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=NULL;}

Handler through Mlooper = Looper.mylooper (); The local variable bound to the thread Looper up, and handler through Mqueue =mlooper.mqueue; Gets the thread's message queue. At this point, handler is bound to the message queue of the thread that created the handler object.

3. Define a method for handling messages: Override public void Handlemessage (Message msg) {}

Subclasses need to override this method to implement the processing method after receiving the message.

4. Start message loop: Looper.loop ()

All preparations are ready, and it's time to start the message loop! The Looper static method loop () implements the message loop.

Looper.java

  Public Static Final voidLoop () {Looper me=Mylooper (); MessageQueue 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 ();  while(true) {Message msg= Queue.next ();//might block//if (!me.mrun) {//Break ; //}            if(msg! =NULL) {                if(Msg.target = =NULL) {                    //No Target is a magic identifier for the quit message.                    return; }                if(me.mlogging!=NULL) Me.mLogging.println (">>>>> dispatching to" + Msg.target + "" + Msg.callback + ":" +msg.what);                Msg.target.dispatchMessage (msg); if(me.mlogging!=NULL) Me.mLogging.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 ("Looper", "Thread identity changed from 0x" + long.tohexstring (Ident) + "to 0x" + long.tohexstring (newident) + "while dispatching to" + Msg.target.getClass (). GE Tname () + "" + Msg.callback + "what=" +msg.what);            } msg.recycle (); }        }    }

while (true) represents the "loop" in the message loop, Looper calls Queue.next () in the loop body to get the next message in the message queue that needs to be processed. When msg! = is null and msg.target! = is null, call Msg.target.dispatchMessage (msg); Distribute the message when the distribution is complete, call Msg.recycle (), and recycle the message.

Msg.target is a handler object that represents the handler object that needs to process the message. The handler void DispatchMessage (Message msg) method is as follows:

Handler.java

 public  void   DispatchMessage (Message msg) { if  (msg.c        Allback! = null   else   { if  (mcallback! = null  ) { if   re                Turn  ;        }} handlemessage (msg); }}

Visible when msg.callback== null and mcallback = = NULL, this example is made up of handlemessage (msg); processing the message, above we say that the subclass overrides this method can implement the message of the specific processing process.

Summary : From the above analysis process, the core of the message loop is that Looper,looper holds the message Queue MessageQueue object, a thread can set Looper as the local variable of the thread, which is equivalent to the thread set up a corresponding message queue. Handler's role is to encapsulate the process of sending and processing messages, so that other threads can send messages to the thread that created the handler only if they need to manipulate handler. Thus, in the previous article, "Android asynchronous processing one: using Thread+handler to implement a non-UI thread update UI interface," the UI thread creates a message loop when it is created (public static final in Activitythread void Main (string[] args), so we can send messages to the UI thread's handler in other threads, to update the UI.

This blog address: http://blog.csdn.net/mylzc/article/details/6771331 reprint please indicate the source

Android asynchronous processing three: Handler+looper+messagequeue in-depth explanation

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.