Android main thread's message system (Handler \ lofter), androidlo

Source: Internet
Author: User
Tags custom name

Android main thread's message system (Handler \ lofter), androidlo


Preface:

Previous articles have written about Bitmap and memory optimization technologies. This article will talk about Handler.

Handler is an important knowledge in the Android system. It is often asked during the Android multi-thread interview and often used in actual projects. Of course, it is also complicated and involves a lot of knowledge. The classes involved include Thread, logoff, Message, and MessageQueue.

Android supports multiple threads. Generally, user-related UI events in an application run in the main thread, such as clicking a screen or button, in order to keep the main thread smooth, users must put time-consuming operations (mainly online operations, large file operations, etc.) into sub-threads without being congested, at this time, you may think of Handler (of course, you can also use other tasks such as Asynchronous tasks. I will talk about it later). But how does Handler relate to Thread? Let's take a look at how the main Android thread is created.

ActivityThread:

There is a main () function in ActivityThread. java, which is the entry for starting an application. The call relation is: startProcessLocked function in ActivityManagerService. java calls the following code:

// Start the process.  It will either succeed and return a result containing// the PID of the new process, or else throw a RuntimeException.Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",                    app.processName, uid, uid, gids, debugFlags,                    app.info.targetSdkVersion, null);

Process. start has done the following operations again, just look at the method annotation, now do not need to know what specific done:

/**     * Start a new process.     *      * <p>If processes are enabled, a new process is created and the     * static main() function of a <var>processClass</var> is executed there.     * The process will continue running after this function returns.     *      * <p>If processes are not enabled, a new thread in the caller's     * process is created and main() of <var>processClass</var> called there.     *      * <p>The niceName parameter, if not an empty string, is a custom name to     * give to the process instead of using processClass.  This allows you to     * make easily identifyable processes even if you are using the same base     * <var>processClass</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 will run.     * @param gid The group-id under which the process will 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 that describes the result of the attempt to start the process.     * @throws RuntimeException on fatal start failure     *      * {@hide}     */    public static final ProcessStartResult start(final String processClass,                                  final String niceName,                                  int 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 through the annotation that the above function will find and execute the main function of ActivityThread. The main function creates a logoff, which is used to create a message processing queue and maintain the Message Queue:

Public static void main (String [] args) {logoff. prepareMainLooper (); // create loginif (sMainThreadHandler = null) {sMainThreadHandler = new Handler ();} ActivityThread thread = new ActivityThread (); thread. attach (false); // all the logic of the application is loved in this method. loop (); // enable a Message loop to continuously read messages in MessageQueue. }
Logoff:

The code for lorule. preparemainlorule () is as follows:

/**     * Initialize the current thread as a looper, marking it as an     * application's main looper. The main looper for your application     * is created by the Android environment, so you should never need     * to call this function yourself.  See also: {@link #prepare()}     */    public static void prepareMainLooper() {        prepare();        setMainLooper(myLooper());        myLooper().mQueue.mQuitAllowed = false;    }

The preceding method annotations have clearly explained that the Logoff of the main thread is created, and this Code is called by the system. First, let's take a look at the operations performed by the prepare method.

/** Initialize the current thread as a looper.      * This gives you a chance to create handlers that then 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 Looper may be created per thread");        }        sThreadLocal.set(new Looper());    }
Private Looper () {mQueue = new MessageQueue (); mRun = true; mThread = Thread. currentThread (); // get the current Thread}

Create the loue of the main Thread. Each loue corresponds to one Thread and one MessageQueue. A MessageQueue is created when a Looper is created. Up to now, the main Thread, logoff, and MessageQueue of the application have been created, and logoff is called. loop (), start to constantly read and process messages from MessageQueue. If there is no Message, wait. Now, with the message loop, The logoff that manages the message loop can send messages and the Handler that processes messages.

Handler:

At this time, you create a Handler in your application. Generally, the following code is used:

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

This Handler is created in the main thread. 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 be able to receive messages. */public Handler () {mlogoff = logoff. mylogoff (); // obtain the logoff if (mlogoff = null) {throw new RuntimeException ("Can't create handler inside thread that has not called logoff. prepare () ");} mQueue = mloue. mQueue; // obtain the MessageQueue mCallback = null for Logoff; // The default value is null. This will be checked when msg is processed later}

After Handler is created, you can use it. For example, you can send a message:

mHandler.sendEmptyMessage(MSG_WHAT);

In the system, the following method will be taken to Handler. java:

/*** Enqueue a message into the message queue after all pending messages * before the absolute time (in milliseconds) <var> uptimeMillis </var>. * <B> The time-base is {@ link android. OS. systemClock # uptimeMillis }. </B> * You will receive it in {@ link # handleMessage}, in the thread attached * to this handler. ** @ param uptimeMillis The absolute time at which the message shocould be * delivered, using * {@ Link android. OS. systemClock # uptimeMillis} time-base. ** @ return Returns true if the message was successfully placed in to the * message queue. returns false on failure, usually because the * logoff processing the message queue is exiting. note that a * result of true does not mean the message will be processed -- if * the logoff is quit before the delivery time of the message * occurs then t He message will be dropped. */public boolean sendMessageAtTime (Message msg, long uptimeMillis) {boolean sent = false; MessageQueue queue = mQueue; if (queue! = Null) {msg.tar get = this; // note that this line of code will be used later. Assign the Handler to the target object sent = queue of Msg. enqueueMessage (msg, uptimeMillis); // put msg in MsgQueue} else {RuntimeException e = new RuntimeException (this + "sendMessageAtTime () called with no mQueue"); Log. w ("logoff", e. getMessage (), e);} return sent ;}

The second method above is the delay in milliseconds, queue. after the enqueueMessage sends a message to MessageQueue, the rest is waiting for the message to be processed. does the loop () method start to poll the Message Queue? The messages you send are read in the loop method. Who will process the messages after reading them? There is a code in the loop () method:

msg.target.dispatchMessage(msg);

Msg is the message you sent to MessageQueue. After reading the message, the target is called. dispatchMessage (). The target is the value assigned to the Handler that sends the message. The Handler itself sends the message. Then, the Handler calls the following method to process the message:

/*** Handle system messages here. */public void dispatchMessage (Message msg) {if (msg. callback! = Null) {handleCallback (msg);} else {if (mCallback! = Null) {if (mCallback. handleMessage (msg) {return ;}} handleMessage (msg); // This will call the handleMessage method rewritten above. }}

Because the callback is empty in the new Message and the mCallback of Handler is null, The handleMessage method rewritten in the new Handler is called.

Summary:

Each thread corresponds to a loose, and each loose corresponds to a MessageQueue. This loose is used to manage Message queues. It mainly reads Message queues and sends messages to the target of the Message for processing. So you should clear the relationship between Thread, Handler, Message, MessageQueue, and logoff.


If you are interested in programming, want to learn more about programming, solve programming problems, and want the system to learn a certain kind of development knowledge, we have a master of java here, C ++/C master, windows/Linux master, android/ios Master, please pay attention to my public account: programmer InterAction alliance or coder_online, Daniel online to provide you with services.


Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Related Article

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.