Handler的PostDelayed底层实现原理
Handler的PostDelayed方法参数是一个Runnable对象。delayMillis为延迟时间,PostDelayed函数实际是调用的SendMessageDelayed方法
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
Runnable会被getPostMessage()函数封装在Message对象的Callback属性中。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
SendMessageDelayed函数会调用SendMessageAtTime, SendMessageAtTime函数会计算出(当前时间+延迟时间 )这个消息需要在什么时间执行作为参数传递。
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
SendMessageAtTime会继续调用enqueueMessage函数
sendMessageAtTime(Message msg, long uptimeMillis)
{
MessageQueue queue
enqueueMessage(queue, msg, uptimeMillis);
}
enqueueMessage将消息发送到主线程的消息队列MessageQueue中,并将发送消息的Handler对象封装到message消息对象的target字段。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // 把发送消息的 handler对象封装到到 msg.target 属性中
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
然后Looper循环器(相当于windows消息机制中的消息循环)会从MessageQueue消息队列中取出Message消息。并通过执行msg.target.dispatchMessage(msg)调用handler对象的dispathchMessage方法。
public static void loop() {
final Looper me = myLooper(); // 返回当前 looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) { // 循环取出queue 中的msg
Message msg = queue.next(); // 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
。。。
final long end;
try {
msg.target.dispatchMessage(msg); // 使用发送消息的 handler 分发消息
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
.....
msg.recycleUnchecked();
}
}
然后handler的dispathMessage方法会判断msg的类型,如果msg.callback不为NULL(也就是我们的Runnable对象),则执行handleCallback(msg)
/*
* 根据 msg 的不同类型分发消息
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//
handleCallback(msg);// 在handler.post(runnable)或 postDelayed(runnable,1000)的时候会执行到这里
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
handleCallback会执行Message.callback.run()也就是Runnable对象的run方法。
注意:因为new Runnable()是创建一个匿名内部类(runnable为接口类)即没名字的类,所以不创建新的线程,还在UI线程中执行run()。