After the interview
Interviewer: You have read the source code of Handler mechanism on your resume. How to improve the priority of Message?
In internal analysis:
First, we analyze that the Message is sent by Handler and then added to The MessageQueue. Looper iterates through the MessageQueue to obtain the Message for execution.
MessageQueue is sorted by time. If you want to increase the priority of Message, you need to place Message before MessageQueue, so that the execution will be prioritized.
The most common ways to send a Message are:
- sendMessage
- sendEmptyMessage
- post
- sendMessageDelayed
- sendEmptyMessageDelayed
- postDelayed
The first three have no delay, and the last three can add delay. Since the first three have no latency, they are generally placed before MessageQueue.
The question is so simple.
A: Sending messages using sendMessage, sendEmptyMessage, and POST puts Message before MessageQueue, so using these three methods can increase the priority of Message.
Interviewer: No.
Although know oneself interview kneel, but still want to take the following mood research, in the end is where the problem?
Reanalyze the process
First, we need to make sure that messages are actually sorted by time in MessageQueue.
MessageQueue insert Message: enqueueMessage(Message MSG, long WHEN), when is actually the delay time.
boolean enqueueMessage(Message msg, long when) { ... synchronized (this) { ... msg.when = when; Message p = mMessages; . if (...) {... } else { ... Message prev; // Sort MessageQueue from smallest to largest for (;;) { prev = p; p = p.next; if (p == null || when < p.when) { break; }... } msg.next = p; // invariant: p == prev.next prev.next = msg; }... } return true; }Copy the code
Let’s look at when for sendMessage(Message MSG) :
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
Copy the code
SendMessage actually calls the sendMessageDelayed method inside, and the delay time is 0.
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
Copy the code
SendMessageDelayed internally calls the sendMessageAtTime method, where the time is systemclock.uptimemillis () + delay time, i.e. Systemclock.uptimemillis () + 0.
public boolean sendMessageAtTime(Message 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;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
Copy the code
EnqueueMessage was called internally in sendMessageAtTime.
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Copy the code
EnqueueMessage calls Queue. enqueueMessage, which is the MessageQueue method we initially analyzed to insert Message.
When sendMessage(Message MSG) is not 0, but systemclock.uptimemillis () + 0.
Systemclock. uptimeMillis() represents the total amount of time since the system was started, in milliseconds.
em…
Is there a way to change when to 0. In this case, the sent Message must precede the MessageQueue because 0 is the smallest. (Of course, you can’t have negative numbers, right? 😂)
To find the answer
Let’s look at how the Handler sends a Message:
Huh? This method has not been seen before:
public final boolean sendMessageAtFrontOfQueue(Message msg) {
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, 0);
}
Copy the code
Is enqueueMessage sendMessageAtFrontOfQueue internal call.
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Copy the code
What? UptimeMillis is 0!! Isn’t that what we want?
Calm down, send and POST correspond, so post should also have a method like this:
public final boolean postAtFrontOfQueue(Runnable r){
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
Copy the code
Well, the results are in!!
Messages can be prioritized using the following methods:
- sendMessageAtFrontOfQueue
- postAtFrontOfQueue
New knowledge, GET!
Guess you like
- Make an App that never crashes
- Custom Gradle Plugin+ bytecode staking
- From handwritten ButterKnife to mastering annotations, AnnotationProcessor
- Here, I want you to write a performance check