声明:本篇文章已授权微信公众号 YYGeeker 独家发布。
前言
对于一个APP来说,启动秒开,切换顺畅的体验能给用户留下良好的第一印象,启动速度对于用户体验及提高用户留存的重要性不言而喻。那么我们首先从它开始入手,从理论结合实际来谈谈有哪些优化启动速度及性能的技巧。
一、介绍
Google 官方介绍文档:https://developer.android.com/topic/performance/vitals/launch-time 有兴趣可以自行阅读。
Google 对应用的启动定义了三个概念,分为冷启动、热启动、温启动。而启动最耗时同时也是我们主要去优化的地方,就是冷启动。在冷启动App之时,手机系统会先执行以下三个任务:
- 点击Launcher APP图标,响应启动App;
- App启动之后展示一个空白的Window;
- 创建App的进程。
这三个任务执行完毕之后,我们的App进程就创建成功了,然后会执行以下操作:
- 创建 APP 对象;
- 启动Main Thread;
- 创建MainActivity;
- 加载视图;
- 布置到屏幕;
- 进行首次绘制。
大致流程如下图所示:
从系统层面来看,一个 Activity 走完 onCreate/onStart/onResume 这几个生命周期之后,只是完成了应用自身的一些配置,比如 window 的一些属性的设置/View树的建立,并没有显示。换句话来说,其实到这一步系统只是调用了 inflate 而已。后面 ViewRootImpl 还会调用两次performTraversals ,初始化 Egl 以及 measure/layout/draw 等。
因此,在Android系统里,我们定义一个应用的启动时间, 肯定不能以Activity 的回调函数作为基准,而应该以用户在手机屏幕上看到我们在 onCreate 的 setContentView 中设置的 layout 完全显示为准,也就是我们常说的应用第一帧。而一旦成了第一次绘制,系统进程就会用Main Activity替换掉之前已经展示的Background Window。
App进程的创建等环节,我们无法去主动干涉控制。那么我们可以优化启动速度的方向有哪些呢? 本篇文章将围绕它展开讨论。
二、分析
Google对启动时长定义了这三个概念:
- ThisTime:最后一个启动的Activity的启动耗时;
- TotalTime:表示自己应用启动的耗时,包括新进程的启动和Activity的启动;
- WaitTime: ActivityManagerService启动App的总耗时(包括当前一个应用Activity的onPause()和自己Activity的启动)
ThisTime、TotalTime 的值在 frameworks\base\services\core\java\com\android\server\am\ActivityRecord.java 文件的 reportLaunchTimeLocked() 函数中计算得到,有兴趣可自行翻阅。
一般来说,开发者只要关心TotalTime即可,这个时间才是我们自己应用真正启动的耗时。一般来说我们可通过如下几种方法检测启动耗时:
2.1 系统log打印
在Android 4.4(API级别19)及更高版本中,系统会输出一个包含名为Displayed的值的输出行。此值表示Activity启动过程和完成在屏幕上绘制相应活动之间所经过的时间长度。
我们在Android Studio的Logcat可以查看这个输出信息,需要注意的是我们在logcat视图中,需要去除过滤器,选择 No Filters。因为系统的输出信息是在系统进程服务,而不是应用程序本身输出的启动日志,具体可参考下图:
2.2 ADB 命令打印
通过adb启动我们的Activity或Service,控制台会输出应用的启动时间,cmd命令格式如下:
adb shell am start -W [packagename/activity]
如执行 手机YY 启动时间统计命令:
adb shell am start -W com.duowan.mobile/com.yy.mobile.ui.splash.SplashActivity
log 打印如下:
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.duowan.mobile/com.yy.mobile.ui.splash.SplashActivity }
Status: ok
Activity: com.duowan.mobile/com.yy.mobile.ui.splash.SplashActivity
ThisTime: 1794
TotalTime: 1794
WaitTime: 1831
Complete
2.3 Trace 文件
通过Trace文件我们也可以分析启动时的相关信息,在ANR触发时,系统会自动生成Trace文件以供我们去分析。一般来说,正常情况下Trace 文件可以有以下几种主动生成的方式:
代码生成
API 19或者以上可以通过如下方式打印trace 文件:
Debug.startMethodTracing("test"); //开始 trace(保存文件到 "/sdcard/test.trace" )
// 省略业务代码...
Debug.stopMethodTracing(); //结束 trace:
使用DDMS
DDMS(Dalvik Debug Monitor Service),是AndroidSDK里面自带的工具,开发环境中对Dalvik虚拟机调试监控的一种服务,它用于对Android的应用程序以及Framework层的代码进行性能分析。具体使用方式可自行查阅资料,这里就不做过多补充了。
2.4 Profile 工具
从上面几个简单