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就被赋值为0for (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