IdleHandler
MessageQueue.IdleHandler 是 Android 中的一个接口,用于在主线程(或任意 Looper 所在线程)消息队列变空闲时执行某些后台或延迟处理任务。它是一种观察“空闲时机”的机制,可以理解为:“当前没有消息要处理了,可以干点别的事”。
接口定义
public static interface MessageQueue.IdleHandler {
boolean queueIdle();
}
唯一方法:
boolean queueIdle();
- 当消息队列进入空闲状态(没有更多消息处理时)调用。
- 返回 true 表示保留该 IdleHandler,继续监听下次空闲;
- 返回 false 表示用完即删,只调用一次。
添加 IdleHandler
通过 Looper.myQueue().addIdleHandler() 添加:
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
Log.d("Idle", "消息队列空闲啦,可以做点事了");
return false; // 只执行一次
}
});
你通常会在主线程中这样使用:
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.getLooper().getQueue().addIdleHandler(...);
典型应用场景
场景 | 说明 |
---|---|
初始化优化 | 把一些不急用的初始化代码放到空闲时执行,避免启动卡顿 |
预加载资源 | 比如图片缓存、数据库预热、UI异步准备等 |
后台清理工作 | 比如缓存目录清理、内存压缩 |
注意事项
空闲时不等于“空转”:
- IdleHandler 只会在处理完所有当前消息、下一条消息还没来之间的短时间内被调用。
不能执行耗时操作:
- 否则会阻塞 Looper,造成 ANR。
- 推荐仅用于轻量任务或任务调度。
仅调用一次(默认行为):
- 若你要持续监听空闲,需要返回 true,但一般不推荐长期挂着,容易影响性能。
IdleHandler 的调用优先级低:
- 有新消息入队就会被打断,不保证一定执行。
示例:在空闲时初始化某个功能模块
Looper.myQueue().addIdleHandler(() -> {
initHeavyComponent(); // 延迟初始化
return false; // 用一次就移除
});
源码调用链简要(Android)
Looper.loop() 每处理完一个 Message 后:
- 如果 mQueue.next() 返回 null(队列无消息)或等待下一条消息时超时,会去触发 IdleHandler。
来自 MessageQueue.nativePollOnce() 的超时返回,会进入:
Message msg = mQueue.next(); // 没有消息
if (msg == null) {
// 调用 IdleHandler
runIdleHandlers();
}
总结
特性 | 说明 |
---|---|
执行时机 | Looper 没有消息可处理、即将进入阻塞等待时 |
用法 | Looper.myQueue().addIdleHandler() |
场景 | 延迟初始化、预加载、后台任务调度 |
是否重复调用 | queueIdle() 返回 true → 多次调用,false → 一次后移除 |