I used postDelay today, and then asked myself what is the difference between postDelay and sendMessage, how to handle the Runnable of postDelay, and then no and then; If you have that question, read along with me, if you know, see if what I said is what you think, or what I said is not good,
1, the message into the team
1. PostDelayed news
Handler handler handler handler handler handler handler handler handler handler handler handler
Public final Boolean postDelayed(@nonNULL Runnable r, long delayMillis) {postDelayed(@nonnull Runnable r, long delayMillis) { We go on to sendMessageDelayed Return sendMessageDelayed(getPostMessage(R), delayMillis); }Copy the code
So here we see that sendMessageDelayed is actually receiving a Message, so let’s go back to postDelayed and see how does that Message handle Runnable
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
Copy the code
Here we see that we put Runnable in message. callback, and then pass Message to sendMessageDelayed, and that’s it
Private static Message getPostMessage(Runnable r) {// message.obtain () returns a new Message instance from the global pool. Allows us to avoid assigning new objects in many cases: Message m = message.obtain (); m.callback = r; return m; }Copy the code
Now let’s move on to sendMessageAtTime
Public Boolean sendMessageAtTime(@nonnull Message MSG, long uptimeMillis) {// If mQueue is empty, prepare is not called. MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, MSG, uptimeMillis); }Copy the code
2. SendMessage is added to the queue
Public final Boolean sendMessage(@nonNULL Message MSG) {// postDelayed() encapsulates Runnable, the logic is the same, return sendMessageDelayed(msg, 0); }Copy the code
At this point we see the message that the queue has been completed, and we continue to look at consumption.
2, consumption
I’m just going to go into looper.loop (), and just to sort through the process a little bit, The relationship between thread and Handler Looper MessageQueue is that a thread corresponds to a Looper and a MessageQueue corresponds to multiple handlers. Since a MessageQueue corresponds to multiple handlers, Does Handler_A send a message and Handler_B get it at the same time, and the answer is no, as we’ll see below. 1. Obtain the Looper of the current thread. 2. Obtain the MessageQueue 3. 4. MSG consumption
public static void loop() { //1. Getlooper final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); MessageQueue final MessageQueue queue = me.mqueue; . boolean slowDeliveryDetected = false; for (;;) MSG = queue. Next (); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; }... Object token = null; if (observer ! = null) { token = observer.messageDispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid); Try {4. MSG consuming MSG. Target. DispatchMessage (MSG); if (observer ! = null) { observer.messageDispatched(token, msg); } dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) {} ... msg.recycleUnchecked(); }}Copy the code
Now don’t worry, let’s go to step 4 and see what target is,
Public final class Message implements Parcelable {// @unsupportedAPpusage /*package*/ Handler target; }Copy the code
Let’s see where target is assigned
public class Handler { private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) { msg.target = this; }}Copy the code
We’re now going back to step 4 to see MSG. Target. DispatchMessage (MSG); Now we’re going to Handler. DispatchMessage () for what
Public void dispatchMessage(@nonnull Message MSG) {// If MSG. Callback! = null execute handleCallback(), if (msg.callback! = null) { handleCallback(msg); } else { if (mCallback ! = null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}Copy the code
Private static void handleCallback(Message Message) {message.callback.run(); }Copy the code
conclusion
The postDelay() method encapsulates a Message with getPostMessage() before the Message is queued, and determines whether to execute runnable.run () at the consumer by checking whether msg.callback is empty. Handler The various POST /send apis are essentially the same. This is just to allow users to avoid manually encapsulating messages in simple cases and simply provide a Runnable
Just some personal summary, if there is no way to welcome everyone to exchange, typos also please point out.