Android 启动速度优化

187 阅读2分钟

启动流程

beeb02654d5a661a7c8b525a4154746.png

启动状态

冷启动

冷启动是指应用重头开始启动,会走遍启动流程全部步骤。

热启动

在热启动中,系统的所有工作就是将 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 步骤)