An analysis of the relationship between Handler,looper,message,messagequeue

Source: Internet
Author: User

first, take a look at the use of the process

1. Using handler instances in child threads

    /*********** Child Threads Use Handler instance *********/    private class Looperthread extends thread    {public        Handler Handler;        @Override public        Void Run ()        {            looper.prepare ();            Handler = new Handler ()            {                @Override public                void Handlemessage (Message msg)                {                        }            };            Looper.loop ();        }    }

2. Handler,looper used in the main thread (UI thread), etc.In fact now the Android/app/acitvitythread.java file, as follows:

public static void Main (string[] args) {//The preceding series of configurations do not care Samplingprofilerintegration.start () for the time being;        Closeguard.setenabled (FALSE);        Environment.initforcurrentuser ();        Eventlogger.setreporter (New Eventloggingreporter ());        Security.addprovider (New Androidkeystoreprovider ());        Final File Configdir = Environment.getuserconfigdirectory (Userhandle.myuserid ());        Trustedcertificatestore.setdefaultuserdirectory (Configdir);        Process.setargv0 ("<pre-initialized>");         /************ from here, use looper*******************/looper.preparemainlooper ();//contrast: Use Looper.prepare () in child threads;        Activitythread thread = new Activitythread ();         Thread.attach (FALSE);         if (Smainthreadhandler = = null) {Smainthreadhandler = Thread.gethandler ();//contrast: Create a new Handler ()} from a child thread if (false) {Looper.mylooper (). setmessagelogging (New Logprinter (Log.debug, "activityt        Hread ")); } Looper. loop ();//contrast: Here Both the same throw new RuntimeException ("Main thread loop unexpectedly exited"); }

Second, view the source code:(i) Prepare ()1, look at the source of Looper.prepare () :
    /** initializes the current thread to a looper. So you can create a handlers before the start loop, and then reference the Looper;      * Make sure to call the #loop () method after calling this method; end this method use #quit (); */public    static void Prepare () {        prepare (true)         ; Contrast: Below you will see that preparemainlooper in the main thread will use prepare (false)    }     private static void Prepare (Boolean quitallowed) {        if (sthreadlocal.get () = null) {            throw new RuntimeException ("Only one Looper could be created per thread");        }        Sthreadlocal.set (new Looper (quitallowed));    }
attached i) here leads to asthreadlocal, first look at its definition:

    Sthreadlocal.get () would return null unless you ' ve called prepare ().    Static final threadlocal<looper> sthreadlocal = new threadlocal<looper> ();

The Threadlocal class is a special global variable that is only represented by its own thread (the class name also manifests the feature), so the looper of each thread is independent;The Threadlocal class Java itself has been implemented, and Android has optimized it, and the main idea remains:how does threadlocal maintain a copy of a variable for each thread? In fact, the idea of implementation is simple, there is a map in the Threadlocal class that stores a copy of each thread's variable,thekey of the element in map is the thread object, and the value corresponds to the variable copy of the thread .
the previous source refers to the get (), set (0 method is to get and set the thread local variable value corresponding to the current thread.
2, see
   /**     * Initialize The current thread as a looper, marking it as an     * application ' s main looper. The main looper for your application     * are created by the Android environment, so we should never need     * to call T His function yourself.  See also: {@link #prepare ()}     */public    static void Preparemainlooper () {        prepare (false);        Synchronized (looper.class) {            if (smainlooper! = null) {                thrownew illegalstateexception ("The main Looper has AL Ready been prepared. ");            Smainlooper = Mylooper ();        }    }       /**     * Return The Looper object associated with the current thread.  Returns     * NULL if the calling thread is not associated with a Looper.     *    /public static Looper Mylooper () {        return sthreadlocal.get ();    }
attached II):Smainlooperdefinition of:

    private static Looper Smainlooper;

roughly the same as before, just defines a Smainlooper , get sthreadlocal get a looper, let Smainlooper point to it;

Two Handler

1, handler part of the source code:

Handler many constructors:

    Public Handler () {This (null, false);    } public Handler (Callback Callback) {This (Callback, false);    } public Handler (Looper Looper) {This (Looper, NULL, FALSE);    } public Handler (Looper Looper, Callback Callback) {This (Looper, Callback, false);    } public Handler (Boolean async) {This (null, async);        } public Handler (Looper Looper, Callback Callback, Boolean async) {mlooper = Looper;        Mqueue = Looper.mqueue;        Mcallback = callback;    masynchronous = async; }/**************** focuses on this constructor *********************/public Handler (Callback Callback, Boolean async) {if (find_            Potential_leaks) {final class<? extends handler> Klass = GetClass (); if (Klass.isanonymousclass () | | klass.ismemberclass () | | klass.islocalclass ()) && (Klass.getmo Difiers () & modifier.static) = = 0) {LOG.W (TAG, "the following Handler class should Be static or leaks might occur: "+ klass.getcanonicalname ()); }}/*************** before ignoring, starting from here to see ******************/mlooper = Looper.mylooper ();//still acquired through sthreadlocal to the current th Read the Looper instance, which is visible here together if (Mlooper = = null) {throw new RuntimeException ("Can ' t creat        e handler inside thread that have not called looper.prepare () ");   } mqueue = Mlooper.mqueue;        Here MessageQueue is looper and handler communication bridge Mcallback = callback;    masynchronous = async; }
attached i)Mqueuedefinition of:FinalMessageQueue Mqueue;

Visible through the Messagequeue,handler and Looper linked together;

(iii) Looper.loop () process of event processing

    public static void Loop () {final Looper me = Mylooper ();//still gets the Looper instance of the current thread through sthreadlocal if (me = = null) {throw new RuntimeException ("No Looper;        Looper.prepare () wasn ' t called on this thread. ");        Final MessageQueue queue = me.mqueue;//Gets the MessageQueue mqueue binder.clearcallingidentity () mentioned above;        Final Long ident = Binder.clearcallingidentity (); /**************** loop Processing message *******************/for (;;) {Message msg = Queue.next ();//Remove next message from MessageQueue if (msg = = NULL) {//No mess                Age indicates, the message queue is quitting.            Indicates that the current MessageQueue is exiting return;            }//debug information, skip Printer logging = me.mlogging;                        if (logging! = null) {logging.println (">>>>> dispatching to" + Msg.target + "" +            Msg.callback + ":" + msg.what); }/** StartDispatch message */Msg.target.dispatchMessage (msg); definition in//message handler target, so DispatchMessage             Finally call the processing function in handler; /** Debug Information, Skip */if (logging! = null) {logging.println ("<<<<< finished to" + msg.t            Arget + "" + msg.callback);            } final Long newident = Binder.clearcallingidentity (); if (ident! = newident) {LOG.WTF (TAG, "Thread identity changed from 0x" + Long.tohex                        String (ident) + "to 0x" + long.tohexstring (newident) + "when dispatching to"            + Msg.target.getClass (). GetName () + "" + Msg.callback + "what=" + msg.what); } msg.recycleunchecked ();//Recycle Processed messages message}}
The Upper loop () method can simply conclude that looper is used to process the extracted message in MessageQueue, which is shared by MessageQueue handler and Looper, The message taken is referred to handler for processing. Handler is also able to add a message to the MessageQueue by post or send for looper subsequent removal. Sthreadlocal ensures that the looper is thread-private and that all information is sent and processed in this thread.

    prepare () is used to create a key-value pair for the thread in sthreadlocal that corresponds to the thread looper, and the gethandler created by new handler or handler is obtained from Sthreadlocal.get (). The created handler and Looper shared Messagequeue;loop begin to cycle through the events in the MessageQueue. It is the entire process.

An analysis of the relationship between Handler,looper,message,messagequeue

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.