IdleHandler属于MessageQueue内部接口,只有一个queueIdle()方法声明。通过方法addIdleHandler将我们的idleHandler添加到集合中。
public final class MessageQueue { private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>(); /** * Add a new {@link IdleHandler} to this message queue. This may be * removed automatically for you by returning false from * {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is * invoked, or explicitly removing it with {@link #removeIdleHandler}. * * <p>This method is safe to call from any thread. * * @param handler The IdleHandler to be added. */ public void addIdleHandler(@NonNull IdleHandler handler) { if (handler == null) { throw new NullPointerException("Can't add a null IdleHandler"); } synchronized (this) { mIdleHandlers.add(handler); } } /** * Callback interface for discovering when a thread is going to block * waiting for more messages. */ public static interface IdleHandler { boolean queueIdle(); }}IdleHandler的queueIdle方法何时执行
在MessageQueue取消息的next方法中,IdleHandler相关代码如下:
@UnsupportedAppUsage Message next() { ... int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { ... if (msg != null) { ... // If first time idle, then get the number of idlers to run. // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future. if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { //如果消息队列为空或者消息执行时间还未到,则获取IdleHandler队列的大小,下面需要用到 pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. //无需要执行的 idle handler,则继续阻塞 mBlocked = true; continue; } if (mPendingIdleHandlers == null) { mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; } //将IdleHandler列表转为数组 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); } // Run the idle handlers. // We only ever reach this code block during the first iteration. for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers; mPendingIdleHandlers = null; // release the reference to the handler boolean keep = false; try { keep = idler.queueIdle(); //开始顺序执行所有IdleHandler的queueIdle方法 } catch (Throwable t) { Log.wtf(TAG, "IdleHandler threw exception", t); } if (!keep) { //如果发现有queueIdle()方法返回false,则线程安全地删除这个idlehandler不再执行queueIdle synchronized (this) { mIdleHandlers.remove(idler); } } } ... } }多任务延迟初始化实战:
我们根据queueIdle返回true时可以执行多次的特点,可以实现一个任务列表,然后从这个任务列表中取任务执行。
public class TaskDispatcher { private Queue<Runnable> delayTasks = new LinkedList<>(); private MessageQueue.IdleHandler idleHandler = () -> { if (delayTasks.size() > 0) { Runnable task = delayTasks.poll(); if (task != null) { task.run(); } } return !delayTasks.isEmpty(); //只要task任务不为空,就继续执行初始化 }; public TaskDispatcher addTask(Runnable task) { delayTasks.add(task); return this; } public void start() { Looper.myQueue().addIdleHandler(idleHandler); }}创建一个ARouter初始化和Webview初始的task
public class WebviewInitTask implements Runnable { @Override public void run() { Log.i("minfo", "初始化Okhttp"); }}public class WebviewInitTask implements Runnable { @Override public void run() { Log.i("minfo", "初始化Webview"); }}界面显示后进行调用:
override fun onCreate(savedInstanceState: Bundle?) { setTheme(R.style.AppTheme) super.onCreate(savedInstanceState) TaskDispatcher() .addTask(ARouterInitTask()) .addTask(WebviewInitTask()) .start() }打印执行结果