启动流程
启动状态
冷启动
冷启动是指应用重头开始启动,会走遍启动流程全部步骤。
热启动
在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必要重复执行对象初始化、布局加载和绘制
温启动
温启动包含在冷启动期间发生的部分操作,同时开销比热启动高。有许多潜在状态可视为温启动,例如:
1、用户在退出应用后又重启启动应用。进程可能未被销毁,继续运行。但应用需要执行 onCreate() 重头开始新创建 Activity
2、系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到 onCreate() 的已保存的实例 savedInstanceState 对于完成此任务有一定助益
启动耗时统计
1、查看日志
过滤 Displayed 日志
2、am 命令
adb shell am start -S -W packageName/activityName -S stop 关闭后再启动
Stopping: com.lixuanlin.performancetest
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.lixuanlin.performancetest/.MainActivity }
Status: ok
Activity: com.lixuanlin.performancetest/.MainActivity
ThisTime: 639
TotalTime: 639
WaitTime: 679
Complete
WaitTime:包括前一个应用 Activity pause 的时间和新应用启动的时间
ThisTime:表示一连串启动 Activity 的最后一个 Activity 的启动耗时
TotalTime:表示新应用启动的耗时,包括新进程的启动和 Activity 的动起,但不包括前一个应用 Activity pause 的耗时
CPU Profile
用于替代 traceview,结束节点 onWindowFocusChanged
高于等于8.0
Run/Debug Configurations -> Android App -> app -> Profiling -> Start this recording on startup -> CPU activity -> profile 方式运行 app (profile 方式运行会影响代码执行效率)
Sample Java Methods (对 Java 方法采样,会出现有些方法没有统计到)
Trace Java Methods (一直跟踪)
Call Chart:根据时间线查看调用栈,便于观察每次调用是何时发生的
橙色:系统 api
绿色:自己的代码
蓝色:第三方代码
横向范围越大耗时越多,鼠标放到横条上显示耗费时间 上面的调用下面的方法,下面有多块表示调用了多个方法,左在前右在后 调用顺序 上 -> 下
Flame Chart(火焰图):根据消失百分比查看调用栈,便于发现总耗时很长的调用链 调用顺序 下 -> 上 从下往上看
Top Down:查看记录数据中所有方法调用栈,便于观察其中每一步所消耗的精确时间 列出所有方法的执行顺序和耗时 蓝条表示存在耗时
Bottom Up:相对于 Top Down Tree,能够更方便查看耗时方法如何被调用
< 8.0
手动启动 CPU Profile
//Application 中启动
//tracePath SD卡的相对路经,需要文件写入权限
Debug.startMethodTracing("")
//onWindowFocusChanged 中关闭
Debug.stopMethodTracing()
到生成目录直接双击打开
StrictMode 模式
StrictMode 是一个开发人员工具,它可以加检测出我们无意中做的事情,并将他们提醒我们注意,以便我们能够修复他们。 StrictMode 最常用于捕获应用程序主线程上的磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectDiskReads() //读操作
.detectDiskWrites() //写操作
.detectNetwork()
.penaltyLog() //违规打印日志提醒
.build()
)
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects() //Sqlite对象泄漏
.detectLeakedClosableObjects() //未关闭的Closable对象泄漏
.penaltyLog() //违规打印日志提醒
.penaltyDeath() //违规崩溃提醒
.build())
}
penaltyLog:发生违规时通过打印日志提醒我们
penaltyDeath:发生违规时应用将发生崩溃
启动黑白屏
1、新建主题并设置 android:windowBackground 属性。
2、设置新建主题给启动的 Activity。
3、最后在 Activity 的 onCreate 方法中使用 setTheme 设置回默认主题。
启动优化相关建议
1、合理使用异步初始化、延时初始化、懒加载机制
2、启动过程中避免耗时操作
3、类加载优化,提前异步执行类加载
4、合理使用 IdleHandler 进程延时初始化
5、简化布局
6、布局优化,使用 AsyncLaoutInflater, 但是 AsyncLaoutInflater 不支持 Handler 创建,不支持 fragment
7、multidex 优化,字节提供的方案(移除 dex -> zip 步骤)