Note:Here is just a process of sendmessage, post is similar
If we need to send a message, the sendMessage method will be called
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
This method will call the following method
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, () + delayMillis); }
Next set the delay time, and then continue to call the sendMessageAtTime method.
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); ("Looper", (), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); }
Here we get the message queue, check whether the queue exists, and then return the execution result of the enqueMessage method. This result is a boolean value indicating whether the message can enter the queue.
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { = this; if (mAsynchronous) { (true); } return (msg, uptimeMillis); }
Here is the queue processing for messages, and the following is the queue for messages in MessageQueue.
boolean enqueueMessage(Message msg, long when) { if ( == null) { throw new IllegalArgumentException("Message must have a target."); } if (()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( + " sending message to a Handler on a dead thread"); (TAG, (), e); (); return false; } (); = when; Message p = mMessages; boolean needWake; if (p == null || when == 0 || when < ) { // New head, wake up the event queue if blocked. = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. needWake = mBlocked && == null && (); Message prev; for (;;) { prev = p; p = ; if (p == null || when < ) { break; } if (needWake && ()) { needWake = false; } } = p; // invariant: p == = msg; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }
It means to encapsulate the passed messages and put them in the queue. At this point, our sendMessage is processed, and the result returned is the Boolean value of whether the queue is successful. So how is the message processed afterwards?
We can see that when the Handler is constructed, a Looper object is recorded and a return function is also recorded.
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((() || () || ()) && (() & ) == 0) { (TAG, "The following Handler class should be static or leaks might occur: " + ()); } } mLooper = (); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called ()"); } mQueue = ; mCallback = callback; mAsynchronous = async; }
The myLooper method here returns a Looper object associated with the current thread.
public static @Nullable Looper myLooper() { return (); }
When Looper is instantiated, it will execute its own prepare method and then execute the loop method. The loop method is to continuously read the messages in the message queue and then perform the corresponding operation. Because it is a loop executed in other threads, it will not affect other threads.
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; () wasn't called on this thread."); } final MessageQueue queue = ; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. (); final long ident = (); for (;;) { Message msg = (); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = ; if (logging != null) { (">>>>> Dispatching to " + + " " + + ": " + ); } (msg); if (logging != null) { ("<<<<< Finished to " + + " " + ); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = (); if (ident != newIdent) { (TAG, "Thread identity changed from 0x" + (ident) + " to 0x" + (newIdent) + " while dispatching to " + ().getName() + " " + + " what=" + ); } (); } }
If a message is read in the loop, the dispatchMessage method will be executed, and then after dispatching the message, the recycleUnchecked method will be executed again to reuse the Message. We see the dispatchMessage method
public void dispatchMessage(Message msg) { if ( != null) { handleCallback(msg); } else { if (mCallback != null) { if ((msg)) { return; } } handleMessage(msg); } }
Here I see that a handlerMessage method is directly executed. This method is a callback method. We must implement it, otherwise the Handler will not do anything. Why? Do you remember when we just said that when we constructed the Handler, we recorded a CallBack return? The handlerMessage method in Handler is an empty method. If we rewrite this method, the code we wrote first will be executed during the callback, that is, what to do after receiving the message.
public interface Callback { public boolean handleMessage(Message msg); } public void handleMessage(Message msg) { }
Here is a brief introduction to the whole process:
After we instantiate a subclass of Handler and override the handleMessage method, the system has done several things for us at this time.
1. Instantiated a message queue MessageQueue
2. Instantiate an associated Looper object and let Looper continuously read the message queue
3. Record the handleMessage method we rewritten as the method we need to callback.
When we execute the sendMessage method of Handler, the system will add the Message object we passed to the message queue. At this time, if Looper reads the message, it will send the message out, and then call back the handleMessage method to execute the code we set.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.