Android Source Learning-----Handler mechanism

Source: Internet
Author: User
Tags prepare

Handler

1. Why use handler

After Android4.0, Google is considering the use of the system and the user experience, if you do some time-consuming operations, do not allow directly in the main thread, but to send a message object by handler method to modify the main thread UI interface

2.Handler Principle Introduction

In all UI interfaces, a dead loop (Looper) is being executed to receive and listen to the instructions from the user, but once the instruction is received, it executes immediately.
  当子线程需要修改UI界面时,调用Handler的sendMessage()方法,向主线程发送消息(Message)
  Handler把消息放到死循环Looper的消息队列中(MessageQueue)
  Looper中还有一个死循环的方法,它会不停的从消息队列中取出消息,并将消息发送给handler
  当handler接收到这个消息后就会执行修改UI界面的程序

3 Handler , Message, Messagequene, looper when created?

3.1 Message the Creation

Since the main interface can no longer be directly modified in a child thread, it is necessary to indirectly modify the main interface by creating a method that handler sends a message. So the message is created by us manually when we need to modify the main interface.

Message is generally created in three ways,

(1) Create with the new keyword

  Message msg = new Message ();

(2) using the Obtain () method to create

Message msg = Message.obtain ();

(3) Created with the handler object through the Obtainmessage () method, which proves that handler was created before the message

Message msg = Handler.obtainmessage ();

By observing the source discovery of Obtainmessage () in the Handler object, this method internally invokes the message object created by the Message.obtain (Handler h) method. The This of the parameter represents the handler object that invokes this method.

As you can see in the source code of obtain (Handler h), when this method is called, the Handler object is given the target in the message and a message object is returned, so this method eventually calls the parameterless obtain () method

In the obtain () parameterless method, there is a synchronous code block inside, in which the message object is created with the New keyword in the fast synchronization code. Before it is created, however, it makes a judgment that if there is already a message object in the message pool, it returns the object that already exists, and if it is not NULL in the message pool, it is a new message object. (See 3.1.2 For information on how to store message objects)

3.2 Message How to store message objects

Message is not stored internally as a queue, but instead is stored as a message pool

(1) Mpool defaults to the first message in the message pool, when the obtain () method is called to store the message object, it is first used to determine if the Mpool is empty, and if spool is not NULL, the message object already in the pool is used, if NULL, Then a new Message object

(2) When a message in a message pool is not NULL, that is, spool is not NULL, the spool is assigned to a Messagee object m, when the M object is message 1

(3) The Message object m uses the next property to point to the next message, at which point the m.next corresponds to message 2 and assigns itself to spool, at which point the spool is message 2.

(4) in Let M.next null, that is, let message 1 no longer point to the next message, break the relationship between message 1 and message 2. At this point the spool is message 2

(5) Reduce the length of the message pool by 1, and return the message object, because messages M is the original message object has been removed, so at this point, message 2 is spool becomes the message 1

In short, the obtain () method, when it is determined that there is already a message object in the messages pool, does not call the method once, just as the first message is taken out, and the second message becomes the first message

3.3 Handler the creation process

Handler when we need to modify the UI interface, we need to create it ourselves by using the new keyword, which generally uses an argument-free construction method.

  New Handler () {};

3.4 Looper the creation process

In handler's parameterless construction method, a two-parameter construction method is called, and a line of code calls a Mylooper () method for Looper, which assigns a value to the variable mlooper, which Mlooper is a Looper object

In the Mylooper () method, The Get () method is called by Sthreadlocal to return a Looper object.

From here, it can be inferred that most of the get () methods generally have a corresponding set () method, and by finding Sthreadlocal find the Set () method, you can see the set () method that is called in the Prepare () method.

In the Prepare () method, only a Looper object is created and assigned to Sthreadlooper, and there is no call to load and continue to find where prepare () is called.

The Find Prepare () method is called in the Preparemainlooper () method. Then, as soon as the Preparemainlooper () is found, it will be possible to find out when Looper was called to load.

In Android, the Android UI thread, the main thread, is actually Activitythread.java, by looking at the source code of the Activitythread, find the main () method and find the Preparemainlooper ( ) method is called

It can be inferred that when the main thread of the application is started, the call loads the Preparemainlooper () to create the Looper.

3.5 MessageQueue the creation process

In the handler constructor method, a two-parameter construction method is called, and a line of code is

Looper Object Mlooper Call Mqueue, assigning a value to MessageQueue

So to find Mqueue in the Looper class, you can find MessageQueue in the Looper constructor method, and this method in the prepare () method, through the sthreadlocal call set () method, as a parameter is passed in, Then the creation process is similar to the Looper

In fact, MessageQueue is created by Looper, so it can be inferred that MessageQueue and Looper are also loaded at the start of the main thread UI.

4 What happens when Looper discovers that there is no message in MessageQueue? If there is another message, how will looper be executed?

When Looper discovers that there is no message in MessageQueue, it will go into a blocking state until Looper wakes up and resumes execution of the loop until MessageQueue in the message.

There is a need to understand the mechanisms of inter-process communication in Linux.

4.1 Linux Inter-process communication mechanism in the system

The process of communication between processes in a Linux system is done through pipe pipelines, and Linux has a special file called a handle, which is equivalent to a variable object. A special file has two handles, one is a write handle and the other handle is a read handle.

and the child process corresponding to the write handle, through the write handle to the special file to write data, the main process corresponding to read the handle, constantly read the data in the special file.

When there is no data in the special file, the main process goes into a blocking state and goes to sleep; When a child process starts writing data to a special file, a special Mark W (write) is written, and when the special file receives the special tag W, it wakes up the main process.

4.2 Looper mechanisms for blocking and awakening

Looper blocking and awakening, similar to the process of Linux in the same signaling mechanism, handler is a sub-thread, MessageQueue is a special file, Looper is the main thread.

When there is no message in the MessageQueue message queue, Looper enters a blocking state, and when handler has data written to the MessageQueue message queue, a special tag w (write) is written. When the MessageQueue receives this special Mark W, it wakes Looper to continue reading the message.

5 Messagequene How do I store messages sent by handler?

The message is sent to MessageQueue by handler through the SendMessage () method, which is stored when the MessageQueue receives the message.

In the SendMessage () method, a Message object is passed in, and the Sendmessagedelayed () method is called internally and returned.

In sendmessagedelayed () This method receives two parameters, one is the Message object MSG and the other is

In this method, call the Sendmessageattime () method, which has two parameters, and the first parameter is the message object, which is the message object passed in when the SendMessage () method is called, where it continues to pass.

Another parameter is the delay time plus a current time, because the delay time passed in the Sendmessagedelayed () method is 0, so you can think of this parameter as the time that the message was sent.

In the Sendmessageattime () method, returns the Enqueuemessage () method, which receives two parameters, the incoming message object and the send time of message, that represents when handler sends a message. This method inserts the message sent by the sending handler into the MessageQueue

and the Enqueuemessage () method invokes a two-parameter method in the MessageQueue,

View MessageQueue Source Find the Enqueuemessage () two-parameter method, which receives a message object and the send time of the message.

In this method, the received message is inserted into the MessageQueue by judging whether the message is empty and when the message is sent.

The Mmessage is the first message in the message queue and is assigned to a Message object P, so both Mmessage and P are the first messages at this point.

5.1 Assuming that p is not null now, that is, if the message is not empty

Assuming that p is not null now, that is, if the message is not empty, then the code determines that the statement in the else is executed. A new Message object is defined Prve

(3) In this else statement, there is a loop in which P is assigned to Prev, and P invokes next to point to the second message until p is null, or the time (when) of the message msg that is about to be sent is less than the time of the message sent by P (P.when), When < P.when, the break jumps out of the loop. (assuming that the when value of MSG is greater than a less than B)

At this point P is the second message, and Prev is the first message

(4) When the condition that satisfies the break jumps out of the loop, p is assigned to Msg.next, that is, the next message of MSG is P, and the MSG is assigned to Prev.next, that is, the next message of Prev is MSG

At this point prev is the first message, MSG is the second message, p is the third message

After this, the incoming MSG parameter is inserted into the MessageQueue

5.2 assuming that the message p is null

Mmessage is the first message and assigns a value to P, at which point P is the first message

Suppose the message P is null (p = = null) or the send time is 0 (when = = 0) or MSG is sent less than the Send time of P (when < P.when)

When P is null, the first message is empty, meaning that Message Queuing is null and there are no messages in the queue. The P is assigned to Msg.next, that is, the next message of MSG is NULL, and then the MSG is assigned to the message queue Mmessage The default first message, then mmessage points to MSG, then MSG is the first message in the message queue.

When the time equals 0 o'clock, the message that is to be inserted immediately is 0 o'clock, which means that the message is processed immediately. When the When < P.when, the MSG is inserted before the P

6 How do I send a message to the handler of the specified message?

In the Looper loop method, when the MessageQueue object queue is assigned to the Message object MSG by calling the next method, it is possible to block

Create a Looper object me through Mylooper (), and then create a MessageQueue object queue through me, then return a Message object msg with the next () method of the queue, and make a judgment on MSG,

When MSG is NULL, it proves that there is no message in the message queue, and return returns to the end.

When MSG is not NULL, Handler's DispatchMessage () method is called through the target.

By looking at handler source to find the target, you can know that target is a handler object, when handler send a message to MessageQueue, MessageQueue will save this handler to the target so that when Looper takes the message out of the MessageQueue, it can send the message to the corresponding handler for processing.

Find the DispatchMessage () method in handler, in which you first determine whether callback is Null,callback is actually a runnable object, and when you create a message object through the obtain () method, Obtain () has a two-parameter method that can pass in a handler object H and a Runnable object callback. This is the callback.

If callback is null, call the Handlemessage () method, which is implemented by us in the code.

If callback is not NULL, execute the Handlecallback () method, which calls the callback's run () method internally through the incoming Message object

Simply put, when we wear a message object through the obtain () method, if you pass in a Runnable object callback, the message is distributed through the Handlecallback () method, and if you do not pass the parameter, So, by overriding the Handlemessage () method in your code, we distribute the message ourselves.

If there is any mistake, please correct me, thank you!

Android Source Learning-----Handler mechanism

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.