启动优化可以整体分为两个阶段和两个间隙:
两个阶段:Application阶段和Activity阶段
两个间隙:handle message 间隙和数据加载间隙
Application阶段
App进程由zygote进程fork出来之后调用ActivityThread的main方法,触发bindApplication方法,这是Application阶段的开始。
然后调用attchBaseContext,在这个阶段,针对低端机具有较长的MultiDex耗时做针对性优化。参考“抖音 BoostMultiDex 优化实践”。
installProvider阶段:在这个阶段可以做第三方SDK的初始化。具体可以参考LeakCanary的使用。
onCreate阶段:这里有很多三方库和业务的初始化操作,是通过异步、按需、预加载等手段做优化的主要时机,它也是 Application 阶段的末尾。(App StartUp的使用)
Activity阶段
首先经历的是其onCreate生命周期,这里涵盖了首屏业务优化的主要场景也是开启异步并发的主要时机,在其中有个重要的 setContentView 方法会触发 DecorView 的 install,可尝试对 DecorView 的构建进行预加载;后续自然来到View 构建的阶段,可采用异步 Inflate 配合 X2C(编译期将 xml 布局转代码)以及AsyncLayoutInflater异步加载布局,并提升相应异步线程优先级的方法综合优化;再来到View 的整体渲染阶段,涵盖 measure、layout、draw 三部分,这里可尝试从层级、布局、渲染上取得优化收益。比如减少层级数,勇stub和merge等等。
最后是首屏数据加载阶段,这部分涵盖非常多数据相关的操作,也需要综合性优化,可尝试预加载、缓存或网络优先级调度等手段。例如对于不要立即加载的数据采用IdleHandler进行延后处理。
启动耗时成因
系统资源类型划分出五大成因,分别是:CPU Time、CPU Schedule、IO Wait、Lock Wait 和 IPC
CPU Time:
1、反射:反射的耗时主要是字符串去查找 Method 或者 Field,这个优化策略也可以考虑提前查找 Method 和 Field 缓存起来。像EventbUS里面就用了大量的反射,采用APT的方式在编译期生成对应的文件,从而减少反射的使用。
2.类加载,类的加载过程包括:Load,从 Dex 文件里读取类的信息,可通过类重排优化;Verify,验证指令是否合法等,通过关掉 Class Verify 可以优化该过程,同时高版本的 vdex 也是为了优化 verify 过程而设计,在 dex2oat 的时候做 verify,verify 之后的结果保存成 vdex,后续只需要加载 vdex;Link,给 Field、Method 分配内存,按照名字排序以方便后续反射的时候查找 Field、Method 等,这个过程的优化,art 虚拟机采用了 ImageSpace 的方案进行了优化,将 Link 后的内存保存为 image 文件,后续可以直接 load 这个 image 文件,省去了 Link 过程;Init,类的初始化。
常用工具
TraceView、Systrace、Android Profiler
网友评论