- 方案浅析
- 核心思路
启动时间的计算,无非是end-start
看怎么精确的抓取到这两个timestamp
这个都很简单的方法了
在application里加
public static void long START = System.currentTimeMillis();
问题是,end time要在哪里获取?
假设app的结构如下
application-> splashActivity ->homeActivity
splashActivity做了一些init操作(不包括跳过广告这样的业务,只是必须要init一些第三方lib)
homeActivity才是真正业务上(有交互)的第一个Activity
以homeActivity真正展示界面为end节点。
end time要如何获取?
可能简单来说,那么界面展示出来,就在homeActivity的onResume获取啊。
可是onResume就真的是view已经show出来了么?
答案是否定的。第一次onResume的时候,实际上view还没渲染出来。view.getWidth都拿不到值。
所以这样去计算启动时间,会比实际值小。
所以必须要必须比onResume晚。
晚多久呢?
我们都知道view的绘制是放在主线程,那么等view绘制完,让主线程通知我们就可以了。
这个通知的操作,就利用了IdleHandler的特性。
IdleHandler是在整个消息队列没有任务空闲下来就开始工作。
//getMainLooper().getQueue() api 21
Looper.myQueue().addIdleHandler(new IdleHandler() {
@Override
public boolean queueIdle() {
//你要处理的事情
return false;
}
});
有点像Thread的join方法,Thread-A里调用了 Thread-B join,
那么Thread-A必须等Thread-B 的join跑完。
关于 IdleHandler 在 MessageQueue 与 Looper 和 Handler 的关系原理源码分析见
https://www.jianshu.com/p/a1d945c4f5a6
那么end time的获取,就放在idleHandler里。
在onCreate方法里加入
@Override
public void onCreate(){
...
Looper.myQueue().addIdleHandler(new IdleHandler() {
@Override
public boolean queueIdle() {
long end = System.currentTimeMillis();
long duration = end - Application.START;
// 如果 是测量某个activity的完全启动,这个START时间就放在该activity的全局变量里
return false; //代表只执行一次
}
});
...
}
网友评论