首先了解App的启动流程
冷启动:当应用启动时,后台没有该应用程序,这时候系统会重新创建一个新的进程分配给该应用。然后再根据启动的参数,启动对应的进程组件。
热启动:当应用启动时,后台已有改用的进程,(例如:按back键,home键,应用虽然会退出,但是该应用的进程是依然会保留在系统后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动进程组件。
在启动过程中,有两个重要的进程SystemSever和App Process,职责主要是
1.SystemSever负责应用的启动流程调度,进程的创建和管理,窗口的创建和管理,
2.应用进程被SystemSever创建之后,进行一系列的初始化,组件化,主界面的构建、内容填充
查看启动时间
附几个常用的adb命令
1.adb devices -查看可用的设备
2.adb shell am start -W PackageName/PackageName.MainActivity-查看启动时间
3.adb -s deviceID shell命令 -指定具体设备
thisTime : 最后一个启动的activity的启动耗时
totalTime : 所有的activity启动耗时
waitTime : AMS启动App的activity时的总时间
利用TraceView分析启动时间
在程序的开始和结尾打上trace
运行程序, 会在Android/data/包名/files.之后调用buildpath返回路径即最终结果是:storage/emulated/0/Android/data/包名/files/dmtrace.trace
注意: 需要给程序加上写存储的权限:
通过adb pull将其导出到本地
adb pull /sdcard/TestApp.trace ~/testSpeed.trace
打开DDMS分析trace文件,会出现以下的界面
App优化
启动窗口优化
1.启动窗口,也叫启动项,启动应用的系统会提供一个预置窗口,以减少用户等待时间,
2.主页面布局优化,通过减少冗余或者嵌套布局来降低视图层级,用viewStub替代启动过程中不需要显示的ui
3.在Application或者主Activity的初始化中异步操作非必要的操作代码。
优化线程,
线程优化主要是减少CPU调度带来的波动,让启动时间更稳定,如果有太多的线程一起启动,会给CPU 带来非常大的压力,
1.利用线程池控制线程数量,
2.检查线程间的锁,防止依赖等待,
3.使用合理的启动架构,微信内部使用的mmkernel,阿里的Alpha.
系统调度优化
应用启动的时候,如果主线程的工作过多,也会造成主线程过于繁忙,下面几个系统调度相关的点需要注意
1.启动过程中减少系统调用,避免与AMS,WMS竞争锁。
2.不要启动子进程,如果好几个进程同时启动,系统负担则会加倍,SystemServer 也会更繁忙
3.启动过程中除了 Activity 之外的组件启动要谨慎,因为四大组件的启动都是在主线程的,如果组件启动慢,占用了 Message 通道,也会影响应用的启动速度
4.Application 和主 Activity 的 onCreate 中异步初始化某些代码
GC优化
启动过程中减少GC次数
1.避免大量的字符串操作
2.频繁创建的对象考虑复用
3.转移到Native层实现
IO优化
IO分为网络IO和磁盘IO,启动过程中不建议进行网络IO,对于磁盘IO要细扣。
1.我们要了解启动过程中读了什么文件,多少个字节,buffer有多大,使用了多长时间,在什么线程等一系列信息。
2.进行启动过程中的IO检测
资源重排
利用Linux的IO读取策略,按照读取顺序重新排列,减少磁盘IO次数,
类重排
1.类重排的实现通过 ReDex 的 Interdex 调整类在 Dex 中的排列顺序,具体实现可以参考 Redex 初探与 Interdex:Andorid 冷启动优化
类加载优化
可以在 systrace 生成的文件中看到 verifyClass 过程,因为需要校验方法的每一个指令,所以是一个比较耗时的操作。
App 瘦身
App 瘦身包括代码瘦身和资源瘦身,通常的做法如下:
1.Inspect Code :Android Studio 提供的代码审查工具,实际上是内嵌了 Lint
2.代码混淆
3.图片格式
4.接入资源混淆
5.减少DEX数量
启动网络链路优化
问题和优化点
发送处理阶段:网络库bindService影响前x个请求,图片并发限制图片库线程排队
网络耗时:部分请求相应size大,包括SO文件,cache资源,图片原图大尺寸
返回处理:个别数据网关请求json串复杂解析严重耗时(3s),且历史线程排队设计不合适
上屏阻塞:回调UI线程被阻,反映主线程卡顿严重。高端机达1s,低端机恶化达3s以上
回调阻塞:部分业务回调执行耗时,阻塞主线程或回调线程
优化
1.多次重复的请求,业务方务必收敛请求次数,减少非必须请求。
2.数据大的请求如资源文件、so文件,非启动必须统一延后或取消。
3.业务方回调执行阻塞主线程耗时过长整改。我们知道,肉眼可见流畅运行,需要运行60帧/秒, 意味着每帧的处理时间不超过16ms。针对主线程执行回调超过16ms的业务方,推动主线程执行优化。
4.协议json串过于复杂导致解析耗时严重,网络并发线程数有限,解析耗时过长意味着请求长时间占用MTOP线程影响其他关键请求执行。推动业务方handler注入使用自己的线程解析或简化json串。
业务梳理
这里涉及到具体的业务,每个 App 都不一样,但是所要做的事情都是一样的
按需进行优化加载
优化方向
分布加载:一大化小,优先级高的先加载
异步加载:耗时多的异步化
延期加载:非必须的数据延后加载。
减少activity跳转层级
默认 App 的启动窗口流程
StartingWindow(SystemWindow)
->MainActivity(AppWindow)
大部分三方 App 启动流程
StartingWindow(SystemWindow)
-> SplashActivity(AppWindow)
-> MainActivity(AppWindow)