Explain the internal implementation principle of handler in Android _android

Source: Internet
Author: User
Tags message queue

This article is mainly on the handler and message loop implementation of the principle of source analysis, if unfamiliar handler can see the blog "Detailed Android handler use method", It explains why Android introduced the handler mechanism and how to use handler.

In general, Handler is a mechanism introduced in Android that allows developers to participate in the processing of message loops in threads. When we use handler, we deal with the message most, message is the hanlder mechanism to the developers exposed to the relevant class, you can through the message class to complete most of the operation handler function. But as a programmer, I can't just know how to use handler, but also how to implement it internally. The internal implementation of handler mainly involves the following categories: Thread, MessageQueue and Looper. The relationships between these classes can be described in the following diagram:

Thread is the most basic, Looper and MessageQueue are built on thread, handler is built on Looper and MessageQueue, and we deal indirectly with these relatively low-level classes through handler.

A picture wins thousand words

We discussed the relationship between thread, MessageQueue, Looper, and Hanlder in this article, and we can better understand the relationship between them by using the diagram below for a conveyor belt.

In real life production life, there are a variety of conveyor belts, the conveyor belt is covered with a variety of goods, conveyor belts are driven by the engine rollers have been rolling forward, and constantly have new goods placed at one end of the conveyor belt, the goods are driven by the conveyor belt to the other end of the collection process.

We can think of the goods on the conveyor belt as a message, and the conveyor belts that carry the goods are messages queue MessageQueue. The conveyor belt is driven by the conveyor wheel, we can think of the transmitter wheel as a looper, and the engine rotation is the need for power, we can think of the power supply thread, all the operation of the message loop is based on a thread. Everything is ready, we just have to press the power switch engine will rotate, this switch is Looper loop method, when we press the switch, we are equivalent to execute the Looper loop method, at this time Looper will drive the message queue loop.

What is the equivalent of the Hanlder in the conveyor model? We can see the handler as a conduit for the goods and for the goods: the goods are drawn from one end to the conveyor belt, and the goods are removed from the other side along the pipe. The way we put the goods at one end of the conveyor is equivalent to the sendmessagexxx, sendemptymessagexxx, or Postxxx method that we call handler. This puts the message object into the queue MessageQueue. When the goods are drawn from the other end of the conveyor belt, we call the Hanlder DispatchMessage method, in which we complete the processing of the message.

The following highlights Handler:

Handler is a class that is exposed to the top floor of a developer, built on thread, Looper and MessageQueue.
Handler has multiple constructors, and the signatures are as follows:

    • 1. Publichandler ()
    • 2. Publichandler (Callbackcallback)
    • 3. Publichandler (Looperlooper)
    • 4. Publichandler (Looperlooper, Callbackcallback)

Neither 1th nor 2nd Constructors Pass Looper, both of which get the current thread-bound Looper object by calling Looper.mylooper (), and then save the Looper object in a member field named Mlooper.
The 3rd and 4th Constructors Pass the Looper object, which saves the looper to the member field named Mlooper.
The 2nd and 4th Constructors also pass the callback object, callback is the internal interface in handler, which requires implementing its internal Handlemessage method, and the callback code is as follows:

Public interface Callback {public
  boolean handlemessage (msg);
}

Handler.callback is a means of handling messages, and if this argument is not passed, then the Handler Handlemessage method should be rewritten, which means that in order for Handler to be able to handle the message, there are two ways:
1. Pass a Handler.callback object to the Hanlder constructor and implement the Handler.callback Handlemessage method
2. You do not need to pass the Handler.callback object to the Hanlder constructor, but you need to override the Handlemessage method of the handler itself
In other words, either way, we have to implement the Handlemessage method in some way, which is similar to the design of thread in Java.
In Java, if we want to use multiple threads, there are two ways:
1. Pass a Runnable object to the thread's constructor and implement the Runnable Run method
2. There is no need to pass the Runnable object to the thread's constructor, but to override the run method of thread itself
So as long as the use of multithreading thread, it should be hanlder this need to achieve handlemessage two ways to clear the heart.

We know that we can add messages to message queues through the Sendmessagexxx series method, and we can see the order of these methods by source code,
SendMessage called the sendmessagedelayed,sendmessagedelayed and called the Sendmessageattime.
There are also a series of sendemptymessagexxx methods in handler, and the Sendemptymessagexxx methods call their corresponding sendmessagexxx methods inside and out.

We can see more clearly through the following call graph:

This shows that all sendmessagexxx methods and Sendemptymessagexxx eventually call the Sendmessageattime method.

Let's take a look at the Postxxx method, we will find that the Postxxx method in its internal and call the corresponding Sendmessagexxx method, we can view the next SendMessage Source:

Public Final Boolean post (Runnable R)
{return
  sendmessagedelayed (Getpostmessage (R), 0);
}

You can see the internal call to the Getpostmessage method, the method passed a Runnable object, get a Message object, Getpostmessage source code is as follows:

private static Message Getpostmessage (Runnable r) {message
  m = Message.obtain ();
  M.callback = R;
  return m;
 }

With the above code we can see that in the Getpostmessage method, we create a Message object and assign the incoming Runnable object to the callback member field of the note, and then return the The message in the Post method that carries the runnable information is then passed into the Sendmessagedelayed method. From this we can see that all postxxx methods need to use the Sendmessagexxx method to achieve, so postxxx and sendmessagexxx are not opposites, but postxxx rely on sendmessagexxx, So the Postxxx method can pass the message to the message queue through the Sendmessagexxx method, except that the Postxxx method carries runnable objects (Message.callback) to the messages that are passed in to the message queue.

We can see clearly the invocation relationship between the Postxxx series method and the Sendmessagexxx method through the following diagram:

By analyzing the relationship between Sendemptymessagexxx, Postxxx method and Sendmessagexxx method respectively, We can see that all methods of sending messages directly or indirectly to message queues in handler end up calling the Sendmessageattime method, which has the following source code:

public boolean sendmessageattime (msg, long Uptimemillis) {
  MessageQueue queue = mqueue;
  if (queue = = null) {
   runtimeexception e = new RuntimeException (This
     + sendmessageattime () called with no Mqueue ");
   LOG.W ("Looper", E.getmessage (), e);
   return false;
  }
  Note the following line of code return
  enqueuemessage (queue, MSG, uptimemillis);

The method internally calls the Enqueuemessage method, which has the following source code:

Private Boolean enqueuemessage (MessageQueue queue, message msg, long Uptimemillis) {
  //Note the following line of code
  Msg.target = this;
  if (masynchronous) {
   msg.setasynchronous (true);
  }
  Note the following line of code return
  queue.enqueuemessage (msg, uptimemillis);

There are two things to be aware of in this approach:

    • 1. Msg.target = This

The code binds the target of the message to the current handler

    • 2. Queue.enqueuemessage

The variable queue represents the Message Queuing MessageQueue that handler binds to, by invoking Queue.enqueuemessage (MSG, uptimemillis) We put the message into the queue.

So we can see the complete method invocation order from the following figure:

When we analyze the source of Looper.loop (), we find that Looper has been constantly getting messages from the message queue via the MessageQueue next method, and then through the Code msg.target.dispatchMessage (msg The handler (Message.target) that is bound by this MSG executes the DispatchMessage method for processing the message.
Handler's DispatchMessage source code is as follows:

public void DispatchMessage (message msg) {
  //Note the following line of code
  if (msg.callback!= null) {
   handlecallback (msg);
  } else {
    //Note the following line of code
   if (mcallback!= null) {
    if (Mcallback.handlemessage (msg)) {return
     ;
    }
   }
    Note the following line of code
   handlemessage (msg);
  }

Let's Analyze This code:

1. The first thing to do is to judge that Msg.callback does not exist, Msg.callback is the runnable type, and if Msg.callback exists, then the message is put into the queue by executing handler's Postxxx series method. The following will execute Handlecallback (msg), Handlecallback source code as follows:

private static void Handlecallback (Message message) {
  message.callback.run ();
}

So we can see clearly that we have executed the Msg.callback run method, which is to execute the Run method of the Runnable object passed by Postxxx.

2. If we do not put messages into message queues through the Postxxx series method, then Msg.callback is null, the code continues to execute, and then we judge that the handler member field Mcallback does not exist. Mcallback is the Hanlder.callback type, as we mentioned above, in the handler constructor we can pass the Hanlder.callback type object that needs to implement the Handlemessage method if we pass the Cal in the constructor Lback object, we let callback's Handlemessage method handle the message.

3. If we do not have an object in the constructor that passes in the callback type, then Mcallback is null, then we call handler's own Hanldemessage method, which defaults to an empty method, and we need to rewrite the implementation of the method itself.

In summary, we can see that handler provides three ways to process messages, and there are priority points for processing: first try to get the runnable executed in Postxxx, Second, try to get the Handlemessage method of the callback passed in the handler constructor, and finally let handler own Handlemessage method process the message.

I hope this article will help you understand the handler and message looping mechanisms in Android.

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.