应用的启动分为:冷启动,暖启动和热启动。其中冷启动是我们优化的重点,优化冷启动可能会同时优化暖启动和热启动。
冷启动
是指开机后第一次启动或应用被杀后启动,在启动之前应用的进程不存在。
冷启动过程中系统会:
1、加载和启动应用;
2、启动之后立即展示黑屏的启动窗口;
3、创建应用进程。
一旦应用进程创建,则由进程负责后续的操作。
1、创建app对象;
2、启动主线程;
3、创建main Activity;
4、加载布局;
5、在屏幕上布局;
6、执行首次绘制;
首次绘制以后会去掉黑屏窗口,显示Main Activity的内容。
我们的优化主要集中在APP和Activity的创建过程中。
暖启动
是介于冷启动和热启动之间的一种启动形式,比如:
1、用户退出了应用之后重新启动,进程虽然存在,但是Activity需要重建,重新回调onCreate.
2、进程和Activity都需要重建的情况,但仍然比冷启动的工作要少。
热启动
是系统把你的Activity带到前台的过程。
热启动时系统同样会先显示黑屏的窗口。
启动类型.png
Displayed Log
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
咱们可以在应用启动log中查看带Displayed的Log,查看启动的时间。
这个时间包含:启动进程,创建对象,创建初始化Activity,加载布局,首次绘制。
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
有时候log中会包含一个总时间,这说明Activity的启动时间和应用总启动时间不同,第一个时间就代表Activity的启动时间。
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN
其中: -W: Wait for launch to complete.
-S: Force stop the target app before starting the activity.
通过以上命令,咱们可以统计应用启动时间。
MacBook-Pro:workspace kkl$ adb shell am start -S -W com.lkk.eventconflictdemo/.MainActivity
Stopping: com.lkk.eventconflictdemo
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.lkk.eventconflictdemo/.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.lkk.eventconflictdemo/.MainActivity
TotalTime: 558
WaitTime: 559
Complete
MacBook-Pro:workspace kkl$ adb shell am start -W com.lkk.eventconflictdemo/.MainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.lkk.eventconflictdemo/.MainActivity }
Status: ok
LaunchState: WARM
Activity: com.lkk.eventconflictdemo/.MainActivity
TotalTime: 328
WaitTime: 329
Complete
MacBook-Pro:workspace kkl$ adb shell am start -W com.lkk.eventconflictdemo/.MainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.lkk.eventconflictdemo/.MainActivity }
Warning: Activity not started, its current task has been brought to the front
Status: ok
LaunchState: HOT
Activity: com.lkk.eventconflictdemo/.MainActivity
TotalTime: 122
WaitTime: 134
Complete
我测试用的就是一个简单的单Activity的demo。
从输出结果我们可以看到三种不同的LaunchState:COLD,WARM,HOT。
第一次启动时我添加了-S,会在启动之前杀掉应用,第二,三次我去调了-S。
第二次我点击了返回键,第三次我点击了home键。
reportFullyDrawn()
我们可以手动调用Activity提供的方法reportFullyDrawn()来记录启动时间,输出如下。
system_process I/ActivityTaskManager: Fully drawn com.lkk.eventconflictdemo/.MainActivity: +115ms
怎么定位启动时间问题
咱们可以优化的点主要集中在Application和Activity的create方法中。
Application#onCreate中的耗时操作主要是,全局对象的初始化等。
Activity#onCreate中的耗时操作主要是,复杂布局文件的加载,一些不必要的初始化,耗时操作等。
当然除了这些方法,肯定有很多好用的工具帮助我们定位问题,比如Matrix,DoraemonKit,booster
等。
怎么解决启动时间问题
Application中耗时的解决办法主要是,延迟初始化。对于一些耗时全局对象的创建,可以延迟到真正需要它的时候。
如果你使用content provider初始化组件,可以考虑使用App Startup 替代。
咱们可以考虑布局优化中的方法优化复杂的布局。
可以考虑把一些操作放在子线程中处理。
可以考虑采用懒加载的方式处理一些页面的加载。
以上都是基本的优化方法,我们还可以考虑其他的方式,比如:
1、systrace + 字节码插桩
2、通过 redex 重排列 class 文件
这里只是罗列出来,后边详细学习,并贴学习总结链接。
参考:
1、App startup time
2、Android App 启动优化全记录
3、深入探索Android启动速度优化
4、都9102年了,Android 冷启动优化除了老三样还有哪些新招?
5、Android性能优化笔记(一)——启动优化
网友评论