IdleHandler在源码中的定义:
/**
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
*/
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();
}
Idlehandler是一个接口,IdleHandler 说白了,就是 Handler 机制提供的一种,可以在 Looper 事件循环的过程中,当出现空闲的时候,允许我们执行任务的一种机制。
它只有一个queueIdle方法,会在message queue处理完message后被调用。返回true会保留使用,返回false执行一次之后就会移除掉。
它是MessageQueue的内部接口,内部持有一个IdleHandler集合,可以进行添加和删除元素。
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
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);
}
}
MessageQueue 是一个基于消息触发时间的优先级队列,所以队列出现空闲存在两种场景:
MessageQueue 为空,没有消息;
MessageQueue 中最近需要处理的消息,是一个延迟消息(when>currentTime),需要滞后执行;
使用IdleHandler示例:
示例1:在activity的onCreate中做任务:
Looper.myQueue().addIdleHandler {
//做操作
Log.i("minfo", "idleHandler excute")
false
}
示例2:延迟加载多个任务
在任务管理里加入多个task,addIdleHandler调用之后遍历task队列调用run方法。
public class DelayTaskDispatcher {
private Queue<Task> delayTasks = new LinkedList<>();
public DelayTaskDispatcher addTask(Task task) {
delayTasks.add(task);
return this;
}
private MessageQueue.IdleHandler idleHandler = () -> {
if (delayTasks.size() > 0) {
Task task = delayTasks.poll();
if (task != null) {
task.run();
}
}
return !delayTasks.isEmpty();
};
public void start() {
Looper.myQueue().addIdleHandler(idleHandler);
}
public interface Task extends Runnable {
}
}
使用方式:
DelayTaskDispatcher().addTask {
Log.i("minfo", "excute task1")
}.addTask {
Log.i("minfo", "excute task2")
}.addTask {
Log.i("minfo", "excute task3")
}.start()
打印结果:
![](https://img.haomeiwen.com/i8669504/40cc9dac8863d2d6.jpg)
关于IdleHandler问题
Q:IdleHandler 有什么用?
IdleHandler 是 Handler 提供的一种在消息队列空闲时,执行任务的时机;
当 MessageQueue 当前没有立即需要处理的消息时,会执行 IdleHandler;
Q:MessageQueue 提供了 add/remove IdleHandler 的方法,是否需要成对使用?
不是必须;
IdleHandler.queueIdle() 的返回值,可以移除加入 MessageQueue 的 IdleHandler;
Q:当 mIdleHanders 一直不为空时,为什么不会进入死循环?
只有在 pendingIdleHandlerCount 为 -1 时,才会尝试执行 mIdleHander;
pendingIdlehanderCount 在 next() 中初始时为 -1,执行一遍后被置为 0,所以不会重复执行;
Q:是否可以将一些不重要的启动服务,搬移到 IdleHandler 中去处理?
不建议;
IdleHandler 的处理时机不可控,如果 MessageQueue 一直有待处理的消息,那么 IdleHander 的执行时机会很靠后;
Q:IdleHandler 的 queueIdle() 运行在那个线程?
陷进问题,queueIdle() 运行的线程,只和当前 MessageQueue 的 Looper 所在的线程有关;
子线程一样可以构造 Looper,并添加 IdleHandler;
网友评论