Handler
创建Handler时会获取到当前线程的Looper,也可以设置消息的发送模式(同步/异步)
public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper ==null) {
throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread() +" that has not called Looper.prepare()");
}
mQueue =mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
当调用Handler的post()
和postDelayed()
方法时,最终都会转到enqueueMessage
方法,在enqueueMessage
方法内部,调用到线程所对应的MessageQueue
的enqueueMessage
方法
注:在此处将Meesage
的target
指向了handler
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue
的enqueueMessage()
方法
根据消息的延迟时间,将消息插入合适的位置(从队首开始遍历,如果到队尾或者下个消息的剩余延迟时间大于入队消息的延迟时间,则插入),至此完成消息的入队流程
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//如果当前队列为空(没有mMessages),且延迟时间为0或小于队列第第一个消息的延迟时间,则将消息插入队首
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = 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 && p.target == null && msg.isAsynchronous();
Message prev;
//开始遍历队列,如果到队尾,或者发现比对消息的剩余延迟大于入队消息的延迟,则确定插入目标
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
//判断是否需要唤醒
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
Looper
通过prepare
方法进行创建,同一线程不运行执行多次,主线程Looper
不允许退出,各线程的Looper
对象由ThreadLocal
进行管理。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
loop()
方法内部会获取到对应的MessageQueue
,然后通过循环,不断调用MessageQueue
的next()
方法去取Message
,获取到Message
后,会调用Meeage.target.dispatchMessage(msg)
来进行Message
的处理,当完成Message
的处理后,会调用Message.recycleUnchecked()
方法进行Message
的回收
public static void loop() {
final Looper me = myLooper();
me.mInLoop = true;
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // 可能会阻塞
if (msg == null) {
// No message indicates that the message queue is quitting.
//如果没有消息,标识该Messagequeue正在退出
return;
}
try {
//调用msg的回调方法
msg.target.dispatchMessage(msg);
} catch (Exception exception) {
throw exception;
}
msg.recycleUnchecked();
}
}
MessageQueue
next()
内部有一个for循环,如果单次执行没有取到Message
,则会继续循环(导致该方法阻塞)。方法会从消息列表的队首开始取Message
(不取异步Message
)。如果有需要处理的Message
,会判断Message
的延迟时间是否到,如果已到延迟所需时间,则取出该Message
进行处理,如果没有的,记录下剩余延迟时间,用于下次唤醒。如果该次循环没有取到Message
,则会判断MessageQueue
是否需要退出。如果不需要退出,则继续判断是否有闲时任务需要处理,如果有,则开始对空闲任务进行处理,处理完后继续下一次循环
Message next() {
int pendingIdleHandlerCount = -1; // 只有第一次循环时该值为-1
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//就是在这里根据nextPollTimeoutMillis判断是否要阻塞
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
//判断是否是异步消息, 如果是异步消息则跳过
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//如果有需要处理的消息
if (msg != null) {
//如果延迟时间还未结束
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// 没有更多消息了
nextPollTimeoutMillis = -1;
}
//处理完所有消息才会退出
if (mQuitting) {
dispose();
return null;
}
//执行到这里标识没有要处理的Message消息,则检查是否有闲时任务要处理
if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
//如果没有要处理的闲时程序,就继续循环,等待消息到来
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 执行闲时任务,只在第一次迭代时会到达这个代码块
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
总结
1:准备阶段
- 在主线程中会调用
Looper.prepareMainLooper()
或在子线程调用Looper.prepare()
创建当前线程的Looper
- 在Looper创建时会自动创建一个对应的MessageQueue
- 通过Looper.loop()方法获取到当前线程的Looper并启动循环,从MessageQueue中不断提取Message,若MessageQueue中没有消息,则阻塞