Android main thread message system (Handler\looper)

Source: Internet
Author: User
Tags custom name

Preface:

The previous article is about bitmap and memory optimization technology, this article to everyone talk about handler.

Handler is an important knowledge of the Android system, which is often asked in Android multithreaded interviews and is often used in real-world projects. Of course, more complex, more knowledge, involved in the class has thread, Looper, Message, MessageQueue.

Android is multi-threaded, usually the user-related UI events in the application are running in the main thread, such as tapping the screen, buttons, etc., in order to keep the main thread smooth corresponding user events are not blocked need to put time-consuming operations (mainly networking, operation of large files, etc.) into the child threads, At this point you might think of handler (and of course you can use other things like asynchronous tasks, which you'll talk about later), but how does handler relate to thread? Let's take a look at how the Android main thread is created.

Activitythread:

There is a main () function in Activitythread.java, which is the entry that is launched in an application, The call relationship is: The startprocesslocked function in Activitymanagerservice.java calls the following code:

Start the process.  It would either succeed and return a result containing//the PID of the new process, or else throw a Runtimeexception.proce Ss. Processstartresult Startresult = Process.Start ("Android.app.ActivityThread",                    app.processname, uid, uid, Gids, DebugFlags,                    app.info.targetSdkVersion, NULL);

Process.Start do the following again, just look at the method comments on the line, now do not need to know exactly what to do:

/** * Start a new process. * * <p>if processes is enabled, a new process is created and the * static main () function of a <var>     Processclass</var> is executed there.     * The process would continue running after this function returns. * * &LT;P&GT;IF processes is not enabled, a new thread in the caller's * process is created and main () of <va     R>processclass</var> called there.  * * <p>the nicename parameter, if not an empty string, was a custom name to * give to the process instead of  Using Processclass. This allows easily identifyable processes even if you are using the same base * &LT;VAR&GT;PROCESSCL     Ass</var> to start them.     * * @param processclass the class to use as the process ' s main entry * point.     * @param nicename A More readable name to use for the process.     * @param uid The User-id under which the process would run. * @param GID THe group-id under which the process would run.     * @param gids Additional group-ids associated with the process.     * @param debugflags Additional flags.     * @param targetsdkversion the target SDK version for the app.     * @param zygoteargs Additional arguments to supply to the zygote process.     * * @return An object, describes the result of the attempt to start the process. * @throws runtimeexception on fatal start failure * * {@hide} */public static final Processstartresult St Art (final string processclass, final string nicename, in                                  T uid, int gid, int[] gids, int debugflags, int targetsdkversion,                    String[] Zygoteargs) {try {return startviazygote (Processclass, Nicename, uid, GID, Gids,        DebugFlags, Targetsdkversion, Zygoteargs); } catch (Zygotestartfailedex ex) {LoG.E (Log_tag, "starting VM process through Zygote failed");        throw new RuntimeException ("Starting VM process through Zygote failed", ex); }    }

You can also see that the above function will find the main function of Activitythread and execute it by commenting. The purpose of creating a looper,looper in the main function is to use a thread to create a message processing queue and maintain the message queue:

public static void Main (string[] args) {        looper.preparemainlooper ();//Create Looper        if (Smainthreadhandler = = null) {            Smainthreadhandler = new Handler ();        }        Activitythread thread = new Activitythread ();        Thread.attach (false);//Apply all logic in this method        Looper.loop ();//Turn on a message loop and constantly read message in MessageQueue.    }
Looper:

The code for Looper.preparemainlooper () is as follows:

/**     * 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 ();        Setmainlooper (Mylooper ());        Mylooper (). mqueue.mquitallowed = false;    }

The above method note has been said to be very clear, created the main thread of the Looper, this code is called by the system. First look at what the Prepare method did.

/** Initialize The current thread as a looper.      * This gives you a chance to create handlers      so reference * This looper, 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 Loope R May is created per thread ");        }        Sthreadlocal.set (New Looper ());    }
    Private Looper () {        mqueue = new MessageQueue ();        Mrun = true;        Mthread = Thread.CurrentThread ();//Get current thread    }

The looper of the main thread is created, and each looper corresponds to a thread, a MessageQueue, and a MessageQueue is created when the Looper is created. The main thread (thread), Looper, MessageQueue, call Looper.loop () of the application are created to the current location, and the message is read and processed from MessageQueue, and waits if there is no message. Now that there is a message loop, the Looper that manages the message loop sends the message and the handler that handles the message.

Handler:

This time you create a handler in your app, which is generally the following code:

private static final Handler Mhandler = new Handler () {public        void Handlemessage (Message msg) {            ...            }        }    };

This handler is created in the main thread, and the handler constructor is as follows:

/**     * Default Constructor Associates This handler with the ' queue for the '     * current thread.     *     * If there isn ' t one, this handler won ' t is able to receive messages.     *    /Public Handler () {        mlooper = Looper.mylooper ();//Gets the Looper        if (mlooper = = null) created above in the main thread {            throw New RuntimeException (                "Can ' t create handler inside thread that have not called looper.prepare ()");        }        Mqueue = mlooper.mqueue;//gets looper messagequeue        mcallback = null;//defaults to NULL when processing msg later on line check    }

Once you've created handler, you can use it, such as sending a message:

Mhandler.sendemptymessage (Msg_what);

In the system will go to the end to Handler.java the following method:

/** * Enqueue a message into the message queue after all pending messages * before the absolute time (in Milliseco     NDS) <var>uptimemillis</var>. * <b>the Time-base is {@link android.os.systemclock#uptimemillis}.</b> * you'll receive it in {@link #ha     Ndlemessage}, in the thread attached * to this handler.         * * @param uptimemillis the absolute time at which the message should be * delivered, using the *     {@link Android.os.systemclock#uptimemillis} time-base.  * * @return Returns True if the message is successfully placed in to the * message queue.  Returns false on failure, usually because the * looper processing the message queue is exiting. Note that A * result of true does not mean the message would be processed--if * the Looper is qui     T before the delivery time of the message * occurs then the message would be dropped. */PublIC Boolean sendmessageattime (Message msg, long Uptimemillis) {Boolean sent = false;        MessageQueue queue = Mqueue; if (queue! = null) {Msg.target = this;//Note that this line of code will be used after assigning handler to the target object of msg sent = Queue.enqueuemess                Age (MSG, uptimemillis);//Put MSG in Msgqueue} else {runtimeexception e = new RuntimeException (            This + "sendmessageattime () called with no Mqueue");        LOG.W ("Looper", E.getmessage (), E);    } return sent; }

The second of the above method is the delay of the number of milliseconds, Queue.enqueuemessage send the message to MessageQueue after the rest is waiting for the message to be processed, the front is not said the Looper.loop () method to start polling message queue, The message that you send is read in the loop method, who will handle it after reading it? There is a code in the Loop () method:

Msg.target.dispatchMessage (msg);

MSG is the message you send to MessageQueue, is read and called Target.dispatchmessage (), this target is handler send the message is assigned value, is to send the message handler itself, Then handler calls itself the following method on the line message processing:

/**     * Handle system messages here.     */Public    void DispatchMessage (Message msg) {        if (msg.callback! = null) {            handlecallback (msg);        } else { C6/>if (Mcallback! = null) {                if (Mcallback.handlemessage (msg)) {                    return;                }            }            Handlemessage (msg);//This invokes the Handlemessage method that is overridden above.        }    }

Because callback is empty at new message and handler's Mcallback = NULL, it is called to the Handlemessage method that you override when you above new handler.

Summarize:

Each thread corresponds to a looper, and each looper corresponds to a MessageQueue, which is used to manage the message queue, mainly to read the message queue and send the message to the target to handle. Here you should clear the relationship between thread, Handler, Message, MessageQueue and Looper.

If you are interested in programming, want to know more programming knowledge, solve programming problems, want to learn a certain kind of development knowledge, we have Java master, c++/c Master, Windows/linux Master, Android/ios Master, Please pay attention to my public number: Programmer Interactive Alliance or Coder_online, Daniel Online to provide you with services.

Android main thread message system (Handler\looper)

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.