IdleHandler是什么?
IdleHandler是包含在MessageQueue类中的一个接口,内部只包含一个方法,在消息队列空闲(没有消息或者第一个需要处理的消息在将来执行)时被回调
public static interface IdleHandler {
// 当消息队列空闲时会被回调, 返回值表示是否会被重复执行
// 返回true,会在mIdleHandlers列表中保留,在下次空闲时还会被调用;
// 返回false,会从mIdleHandlers列表中删除,下次不在被调用
boolean queueIdle();
}
mIdleHandlers是一个ArrayList,用于存放需要执行的IdleHandler
IdleHandler是怎么工作的?
IdleHandler的工作过程分为两步:
-
添加IdleHandler
-
执行IdleHandler
首先需要知道IdleHandler是如何储存的,在MessageQueue的变量定义部分可以找到如下代码
// Idler列表,保存着MessageQueue空闲时需要执行的idlers,生命周期和MessageQueue一致
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
// 待执行Idler列表,每次MessageQueue空闲时会被重新赋值
private IdleHandler[] mPendingIdleHandlers;
这两个简单的数据结构是仅有的两个IdleHandler载体。
添加方式很简单,只是使用了List的add操作,调用addIdleHandler即可将需要执行的Idler添加进列表
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
mIdleHandlers.add(handler);
}
}
IdleHandler的回调只有一处,就是在MessageQueue的next方法中
Message next() {
...
int pendingIdleHandlerCount = -1; // -1 only during first iteration
...
for (;;) {
...
synchronized (this) {
...
// 中间省略部分为查找可执行的message的逻辑
// 如果找到则返回该message
// 没有找到则继续向下执行
...
// 从这里往下为IdleHandler相关操作
// 获取要运行的idlers数量.
// 如果是第一次空闲(即第一次进入for循环) && (消息队列为空 || 第一个要执行的message是在将来执行)
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// 如果没有需要执行idle handler则继续轮询
mBlocked = true;
continue;
}
// 创建一个待执行的IdleHandler列表
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// 执行idle handlers.
// 只在第一次空闲时会执行到下面的for循环,因为一旦执行完pendingIdleHandlerCount就被赋值为0
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // 释放掉handler的引用
boolean keep = false;
try {
// 回调IdleHandler,执行queueIdle方法!!
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
// 不需要重复执行的idler从列表中移除
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// 重置为0,使上面的循环不会重复执行.
pendingIdleHandlerCount = 0;
...
}
}
上面省略了部分不太相关的代码,注释已经把IdleHandler的调用过程写的比较清楚了,简单总结就是,第一次找不到可执行message时执行IdleHandler;再找不到可执行message时,轮询查找message不再执行IdleHandler。
IdleHandler能用来干什么?
因为IdleHandler是利用MessageQueue的空闲时间时间来工作的,所以一些不想对app性能产生影响的操作就可以交个IdleHandler来做,比如ActivityThread中的GC操作就是使用IdleHandler执行的。
当然我们也可以利用IdleHandler在主线程把一些工作提前,优化体验,更多使用方法将继续探索。
欢迎关注公众号:从技术到艺术
来源:CSDN
作者:qq_30496695
链接:https://blog.csdn.net/qq_30496695/article/details/103846430