前言
作为系统最重要的部分之一。Handler
可以说是面试必问。本文只要还是介绍 Handler 中的一点IdleHandler
。关于Handler
其他细节可以参考之前笔者记录分析的从源码分析Handler面试问题
IdleHandler 是什么
在Handler
源码中能够找到 如下接口。其注释部分就很好的解释了其作用。简单概述
当消息队列中没有立刻执行的消息时候执行idleHandler的任务
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/
boolean queueIdle();
}
复制代码
如何使用
Handler
提供了两个方法
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
复制代码
public void removeIdleHandler(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
}
}
复制代码
使用起来也非常简单了
Looper.myQueue().addIdleHandler{
Log.i(TAG, "this is meeage")
false
}
复制代码
源码分析
首先从addIdleHandler
开始分析。将IdleHandler
添加到了mIdleHandlers
这个mIdleHandlers
就是一个数组。用来存放idle任务的
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
复制代码
我们都知道 Handler
是在MessageQueue中将消息取出。这里我们具体分析一下IdleHandler
是如何在没有立刻执行的消息时候
去执行此任务。
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
// ? 下面 默认的 idle 任务数量是 -1
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
// ? 看到这里 此时如果msg 为空 说明。此时队列中是没有消息的。也就是所谓的空闲状态
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();
// ? 当有任务的时候 直接返回 不会执行到 idle 的任务
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// ? pendingIdleHandlerCount默认是 -1
if (pendingIdleHandlerCount < 0
// 并且满足了 当前没有消息的时候
&& (mMessages == null || now < mMessages.when)) {
// 记录我们保存的 idle 任务数量
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
// ? 默认是null 会创建一个数组 用于存放 idle任务
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// ? 将 idle 的任务 执行
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 {
// ? idle 的接口是有一个返回值的。
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
// ? 当 返回值是 false只执行一次。当返回true 则 循环执行
if (!keep) {
synchronized (this) {
// ? 当返回false 则会删除 这个 idle 任务
mIdleHandlers.remove(idler);
}
}
}
// ? 重置 idle 任务的数量
// 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;
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END