An in-depth analysis of the Android message mechanism _android

Source: Internet
Author: User
Tags message queue

In Android, messages are often used for information interaction within threads or between threads, and if we are familiar with its internal principles, it will make it easier and better to structure the system and avoid some low-level errors.

Each android application creates a thread that is called the primary or UI thread when it starts, and all of the actions that Android applies will run on this thread by default.
But when we want to make data requests, picture downloads, or other time-consuming operations, it is impossible to do this on the UI thread, because Android has banned this in the version after 3.0, throwing an exception directly. So we need a child thread to handle things that are in addition to UI operations.

But there's a problem with the UI thread process UI, which can only be time-consuming in a child thread, and what should we do if we need to display a view on the Android screen after the time-consuming operation is over? It is impossible for us to refresh the UI directly on the child thread. At this point we need to use the Android message mechanism to implement the main thread and child thread communication. In short, after the child thread gets the data, not directly to the UI update, but the data loaded into the message sent to the main thread, the main thread in a circular polling immediately received the Cheng message, and then get the message data in the main thread to update the UI. It's simpler to say, let's take a closer look at the specifics.

means of handling messages--handler, Looper, MessageQueue

Handler

Let's talk first. Handler,handler, as the name suggests, is typically used to create a new handler in the UI thread, overwrite his handlemessage, and then post the message to the UI thread in a time-consuming thread, as the following example:

Class MyHandler extends handler{
@Override public
void Handlemessage (msg) {
//update UI
}
}
MyHandler Mhandler = new MyHandler ();
New Thread () {public
void run () {
mhandler.sendemptymessage (123);
};

This stipulates that handler must be created in the main thread because the UI thread creation will allow handler to be associated with the existing MessageQueue. And the MessageQueue is encapsulated into the looper, and Looper is encapsulated into a thread through threadlocal, and finally the equivalent of MessageQueue associated with a thread. So simply put, handler the message to a MessageQueue that is associated with the thread, and then handler takes the message out of MessageQueue and processes it.

Let's take a look at the 2 common methods of handler.

void Handlemessage (Message msg): Method of processing Messages
final Boolean SendMessage (Message msg): Send messages now

The first method we usually execute in the UI thread is typically used to refresh the UI, as if creating a non-static inner class generates a memory leak, It is recommended that you refer to the memory leak caused by this blog handler. The second method, which we usually execute in a child thread, requires a handler object, usually by the main thread, to be passed to the child thread. And you need a message object that specifies his msg.what as a sign of the messages, but if we just use handler to process a message, choosing the Post method is a better choice, as the following example:

Private Handler Mhandler = new Handler ();
New Thread (New Runnable () {
@Override public
void Run () {
mhandler.post (new Runnable () {
@Override Public
void Run () {
//ui operation
...}}
);

Here we go on to discuss the message of the loop queue MessageQueue and wrapping his looper loop

Looper and MessageQueue

It is mentioned above that creating and instantiating handler objects in the UI thread does not require Looper and MessageQueue, as our application executes the Activitythreadmain at startup, where the Java language runs the portal public

static void Main (String [] args) creates a mainlooper in this area, and the procedure is created as follows: public
static void Main (string[] args) {
//initialization C17/>looper.preparemainlooper ();
Activitythread thread = new Activitythread ();
Thread.attach (false);
if (Smainthreadhandler = = null) {
Smainthreadhandler = Thread.gethandler ();
}
Asynctask.init ();
Move Up
looper.loop ();

There is no MessageQueue, we can take a look at the source of the Looper class, to understand the initialization of what happened when the interesting things.

 public class Looper {private static final ThreadLocal sthreadlocal = new ThreadLocal ();
Looper message queues in final MessageQueue mqueue;
Threads thread Mthread current; 。。。 Other attributes//each Looper object has its message queue, and the thread it belongs to is private Looper () {mqueue = new MessageQueue (); mrun = true; mthread = Thread.currentth
Read (); //We call this method to create the Looper object public static final void prepare () {if (sthreadlocal.get ()!= null) in the calling thread's TLS {//attempt to have a looper thread
Creating the Looper again will throw an exception throw new RuntimeException ("Only one looper may is created per thread");
} sthreadlocal.set (New Looper ()); }//Other method} 

We look at this line of code, first of all, instantiate a Threadlocal object, this is used to implement the Looper loop of localized storage, about threadlocal can see why this article with Threadlocal, In short, when multiple threads simultaneously access the Looper object, we do not have to synchronized synchronization mechanism to deal with him, but to create a copy of our own looper for each thread, a thread changes the looper copy of a, does not affect the looper of the B thread, Thus the more efficient implementation of thread safety. The following sentences define the MessageQueue in turn, and the looper is privatized, and the Looper object is set to sthreadlocal in the Prepare method, so MessageQueue is wrapped in the Looper object. At the same time, the thread and looper associations are connected by threadlocal so that message queues are associated with threads, and different threads cannot access each other's message queues.

As shown in the following illustration:

And then there's the Looper.loop loop, and let's take a look at what's going on in the loop method.

public static final void loop () {
Looper me = Mylooper ();//Get current thread looper
MessageQueue queue = me.mqueue;//Get current loo MQ while
(true) {
msg = Queue.next ()///Remove Message
if (msg!= null) {
if (msg.target = null) {return
;
}
Msg.target.dispatchMessage (msg);
Msg.recycle ();}}

This is an elliptical version of the code, we see from here infinite loop execution, first from the message queue to constantly remove the message, and then keep Msg is empty, Whether the msg.target is empty, not empty, the implementation of the DispatchMessage method, this method is a handler method, which we can see Msg.target is the type of handler, thus, through the looper.prepare and loop.loop implementation of the M Essagequeue,looper,handler the relationship between the three. And the handler and the Looper, and the MessageQueue association is in Handler's default constructor, obtains the loop object through the Looper.getlooper, thus obtains the MessageQueue, its source code is as follows:

Public Handler () {
//directly associates the Looper MQ as its own MQ, so its message is sent to the MQ on the associated looper
mlooper = Looper.mylooper ();
Mqueue = Mlooper.mqueue;
Mcallback = null;
}

Our flowchart can then be more content, as follows:

Let's take a look at the DispatchMessage () method, which is actually just a distribution method, and if the runable type callback is empty, the handlermessage is executed to process the message, which is empty and needs to be overridden. If not NULL, the handlecallback is executed. In fact, if we use the handle post method, we execute the callback, and if we use SendMessage, we execute the Handlemessage
Here either post (Runnable callback) or handlermessage is actually calling a method sendmessagedelayed (message msg) It's just that handlermessage takes a parameter directly, and Runable callback actually assigns the Runable object to the callback member variable of the message object, and finally inserts it into the queue. Finally Looper continuously reads the message from the MessageQueue and invokes the handler DispatchMessage message, which is executed in a different way depending on whether the callback is empty. This is the end of the Android messaging mechanism.

Back to the beginning

We know this time why it is necessary to instantiate the handler object in the main thread in order to update the UI refresh, because only messages sent to the UI thread can be processed by the handler of the UI thread, if we want to instantiate handler in a non-UI thread, You must first turn the thread into Looperthread and instantiate it. This means executing the following code:

Loop.prepare ();
hander = new Handler;

Loop.loop

As for the reasons I believe that after reading the above explanation, you should know.
Now let's take a look at our first code and finally the brain to make up for the handler workflow.

Class MyHandler extends handler{
@Override public
void Handlemessage (msg) {
//update UI
}
}
MyHandler Mhandler = new MyHandler ();
New Thread () {public
void run () {
mhandler.sendemptymessage (123);
};

When handler is instantiated into Mhandler, the system completes the handler-Looper association by handler The default constructor, and is associated with Looper through MessageQueue. The looper of the main thread is already constructed by Loop.prepare when the system starts, and is associated with the UI thread through Threadlocal, and then executes the mhandler.sendemptymessage in the new thread, Send message to Messagequeue,looper.loop in the loop, constantly take out the message, to handler processing, in our overwrite handlemessage, identify the messages we send, processing messages. Of course, this is only a empty message, so in the Handlemessage did not perform msg.what judgment.

The above content is small series to introduce the Android message mechanism, I hope to help you!

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.