前面讲Handler的时在MessageQueue源码中看到了IdleHandler的身影
MessageQueue.next()
Message next() {
...
keep = idler.queueIdle();
...
}
IdleHandler是MessageQueue内部定义的静态接口,官方注释清晰的说明了IdleHandler.queueIdle()是在MessageQueue中没有message,等待更多消息时调用。也就是说IdleHandler是在事件循环空闲时执行的。
public static interface IdleHandler {
boolean queueIdle();
}
Activity、Window、View有说到ui绘制是在onResume()回调方法执行后开启的。
ActivityThread.handleResumeActivity()
public void handleResumeActivity(...){
...
//回调onResume()
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
final Activity a = r.activity
...
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
...
//调用到ViewRootImpl.performTraversals()
r.activity.makeVisible();
}
onResume()方法回调在ui绘制前就执行了。如此说来在onResume()生命周期之前,ui线程的任何操作都会延迟ui绘制开始执行的时间。可以把一些ui线程执行的耗时逻辑放在IdleHandler中执行,以此来优化页面的启动时间。由于onResume()和performTraversals()本身都是在Looper的事件循环中执行,所以IdleHandler的queueIdle()方法一定会在ui绘制完毕且MessageQueue无消息处理时执行。
使用起来也很简单,实现IdleHandler()接口重写queueIdle()方法就好。
override fun onResume() {
super.onResume()
Looper.myQueue().addIdleHandler {
//doSomething
//需注意此处返回值。true会保留,每到空闲都会执行;false执行一次后会remove
false
}
}
网友评论