With regard to the handler message mechanism, we have always thought that its function is to send messages to the main thread in the Child thread to update the UI. later, during the interview, I would like to explain in depth the handler mechanism to explain the functions of handler, logoff, message, and messagequeue. At that time, I did not answer the question and regretted it! After going back, I took a hard look at the explanation of a handler mechanism and understood it thoroughly by combining the android source code. After reading it, I have a new understanding of handler. In fact, handler is a mechanism to solve multi-thread (not limited to sub-thread and UI thread) communication.Let's talk less about it. First look at a piece of code:
Package COM. example. handlerdemo; import android. OS. bundle; import android. OS. handler; import android. OS. logoff; import android. OS. message; import android. app. activity; public class mainactivity extends activity {private handler handler2; private handler handler1 = new handler () {@ overridepublic void handlemessage (Message MSG) {system. out. println ("thread->" + thread. currentthread (). GETID () + "received message (" + MSG. what + ")") ;}};/*** receive message */private class recvthread extends thread {@ overridepublic void run () {Looper. prepare (); handler2 = new handler () {@ overridepublic void handlemessage (Message MSG) {system. out. println ("thread->" + thread. currentthread (). GETID () + "received message (" + MSG. what + ")") ;}}; logoff. loop () ;}@ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); recvthread = new recvthread (); sendthread = new sendthread (); recvthread. start (); sendthread. start ();}/*** send message */private class sendthread extends thread {@ overridepublic void run () {message MSG = handler1.obtainmessage (); MSG. what = 1; handler1.sendmessage (MSG); MSG = handler2.obtainmessage (); MSG. what = 2; handler2.sendmessage (MSG );}}}
This code is very simple. When a thread sendthread is enabled, two messages are sent, one accepted by the main thread and the other accepted by the recvthread. In this example, communication between multiple threads is realized. Next, let's take a detailed analysis of how Android achieves this. To understand this, we must first understand several classes:
Message: messages, message processing objects, and processed data are lined up by messagequeue and eventually processed by handler (a member variable target is very important ).
Handler: the handler responsible for sending and processing messages. When using handler, you must implement the handlemessage (Message MSG) method to process specific messages, such as updating the UI.
Messagequeue: a message queue used to store messages sent by handler and run the messages according to FIFO rules. Of course, storing messages is not actually a matter of saving. Instead, messages are connected in a linked list, waiting for the logoff to be extracted.
Logoff: the message pump constantly extracts messages from messagequeue for execution. Therefore, a messagequeue requires a logoff.
In the Android system, message queues and message loops are targeted at specific threads. A thread can exist (or do not exist), a message queue, and a loopse loop ). However, the created worker thread does not have message loops or message queues by default. To enable this thread to have message queues and message loops, you must first call logoff in the thread. prepare () to create a message queue, and then call logoff. loop () enters the message loop. Note that there is an endless loop in the loop () method, so the loop () method must be called at the end of the run () method. Let's take a look at how the loop () function of logoff. Java is implemented:
Public static final void loop () {Looper me = mylooper (); // obtain the corresponding loageobject messagequeue queue = me from this thread. mqueue; // get the message queue object... while (true) {message MSG = queue. next (); // The might block retrieves a pending message from the Message Queue .. // If (! Me. mrun) {// do you want to exit? Mrun is a volatile variable, which is synchronized across threads. It should be set somewhere. // Break; //} If (MSG! = NULL) {If (msg.tar get = NULL) {// No target is a magic identifier for the quit message. Return;} If (Me. mlogging! = NULL) me. mlogging. println (">>>>> dispatching to" + msg.tar get + "" + MSG. callback + ":" + MSG. what); msg.tar get. dispatchmessage (MSG); // note that the target variable here is a handler object if (Me. mlogging! = NULL) me. mlogging. println ("<finished to" + msg.tar get + "" + msg. Callback); msg. Recycle ();}}}
Please get. the dispatchmessage (Message MSG) method extracts the message and submits it to handler for processing. Note that the target here is actually a handler object. The message is sent through the dispatchmessage (Message MSG) method, let's take a look at how this method is implemented:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
This is actually the handlemessage (Message MSG) method of the callback handler, that is, the Message Processing Method inherited when new handler () is in our code. We should understand how the thread extracts and processes messages through logoff. But I believe you will have a question: How do I know the handler to which the message will be handled? There is a target in the message class, that is, the handler object. Where does this object come from? I believe you have guessed it. Yes, it is passed in by the handler. obtainmessage () method. Next we will discuss the detailed process of message sending:
Check the code in the program:
Message MSG = handler1.obtainmessage ();
MSG. What = 1;
Handler1.sendmessage (MSG );
Let's look at the handler. Java's obtainmessage () function:
public final Message obtainMessage() { return Message.obtain(this); }
Let's take a look at the obtain (handler) function of message. Java:
public static Message obtain(Handler h) { Message m = obtain(); m.target = h; return m; }
Here we will pass the reference of the handler object to the target variable of the message, and then add the message to the Message Queue through the sendmessage (Message MSG) method of handler.
The last question is that we didn't call loop in the UI thread. prepare () method, but still can accept messages, because activity is a UI thread and runs in the main thread, when the Android system starts, it creates a message queue and a message loop for the activity ). For detailed implementation, see the activitythread. Java file.
When the android application process starts, it loads the activitythread class in the process and executes the main function of this class. The message loop process of the application is implemented in this main function.
public final class ActivityThread {......public static final void main(String[] args) {......Looper.prepareMainLooper();......ActivityThread thread = new ActivityThread();thread.attach(false);......Looper.loop();......thread.detach();......}}