如何获得app的启动时间?
我也在想这个问题。
当我在framework 代码上做这类测量的时候,我可以精确的得出我需要的东西。但是非framework 开发者如何从普通构建获得自己需要的信息呢?
幸运的是,这个信息是存在的,如果你运行的是4.4(Kitkat)以后的版本,你就可以得到。
你只要启动你的activity ,然后直接在logcat里面查看,寻找这样的log:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +768ms
这个信息在activity 窗口完成所有的启动事件之后,第一次绘制的时候输出。这个时间包括了从启动进程到第一次布局与绘制的所有时间。这基本上是你需要知道的主要时间。它不包含用户点击app图标然后系统开始准备启动activity的时间,这是ok的,因为作为一个开发者你无法影响这个时间,所以没有必要去测量它。
相反,它包含的是在启动时加载代码,初始化类所用的时间。里面都是你真正想测量的时间,因为它们才是你能优化也应该去优化的东西。
前面所提到的 'Displayed' 时间是自动报告的。 快速测量启动初始化需要多久。但是假如你还异步加载一些其它的内容,想知道所有的东西加载完成,绘制需要多久该怎么做呢?
这种情况下,你就需要调用Activity的reportFullyDrawn()。它将在log里报告从apk初始化(和前面Displayed的时间是一样的)到reportFullyDrawn() 方法被调用用了多长时间。
reportFullyDrawn()方法显示的log也是类似这样:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +768ms
译者注:在4.4上调用reportFullyDrawn()方法会崩溃(但是log还是能正常打印),提示需要UPDATE_DEVICE_STATS权限 ,但是这个权限只有系统app才能授权。解决的办法是这样调用:
try{ reportFullyDrawn(); }catch(SecurityException e){ }
还有一种测量启动时间的方法也值得一提,那就是screenrecord命令。
首先启动带—bugreport选项(它可以在frames 中添加时间戳-应该是L中的特性)的screenrecord 命令:
$ adb shell screenrecord --bugreport /sdcard/launch.mp4
然后点击app的图标,等待app显示,ctrl-C screenrecord, 使用adb pull命令把文件导出到电脑。
$ adb pull /sdcard/launch.mp4
现在你可以打开录制视频看看发生了什么。你需要一个能逐帧查看的视频播放器(mac上的Quicktime 就可以,不清楚其它os上什么播放器这个功能最好使)。现在逐帧播放,注意视频的上方有一个frame 时间戳。
一直往前直到你发现app图标高亮了为止。这个时候系统已经处理了图标上的点击事件,开始启动app了,记录下这一帧的时间。继续播放帧直到你看到了app整个UI的第一帧为止。根据不同情况(是否有启动窗口,是否有启动画面等等),事件和窗口发生的实际顺序可能会有不同。对于一个简单的app来说,你会首先见到启动窗口,然后渐变出app真实的UI。在你看到UI上的任何内容之后,你应该记录下第一帧,这时app完成了布局和绘制,准备开始显示出来了。同时也记录下这一帧所发生的时间。
现在把这两个时间相减 ((UI displayed) - (icon tapped)); 得到app从点击到绘制就绪的所有时间。虽然这个时间包含了进程启动之前的时间,但是至少它可以用于跟其他app比较。
现在你知道如何计算启动时间了,不管你用什么方法,能让app变快就是了。
英文原文: Measuring Activity Startup Time 。