在启动优化方面除了常规的设置主题图片
防止出现白屏或黑屏,Application 的 onCreate 方法里精简业务逻辑和三方 SDK 异步或者延迟初始化,精简首屏页面的复杂度等之外,现在有了一个新选择,就是字节出品的BootMultiDex框架。
背景
我在开发阶段其实一直在关注 App 的启动时间,Android5.0 及以上在混淆后表现良好,几乎看不到黑屏,但是在Android4.4
上,在做了上述常规优化后,在 App 未混淆前,启动时的黑屏能达到 4-5s,混淆后依然有 1-2s 的黑屏时间,而且默认主题图片停留的也较长,这时就不得不采用一些手段来进行优化,在做了一番调研后,发现字节出品的 BoostMultiDex 很契合我们现在的需求,它是一款用于 Android 低版本设备(4.X 及以下,SDK < 21)快速加载多 DEX 的解决方案。
MultiDex 过程
MultiDex
会在主线程中对 APK 内的原始 DEX 文件做 ODEX 优化
sequenceDiagram participant APK as APK participant FileSystem as 文件系统 participant DexFile as DexFile participant odex as classesN.odex participant dexPathList as dexPathList.dexElements APK->>FileSystem: 解压 classes2.dex (Secondary dexes) FileSystem->>FileSystem: 压缩成 classes2.zip FileSystem->>DexFile: DexFile.loadDex 优化 classes2.zip DexFile->>odex: 生成 classes2.odex DexFile->>dexPathList: 添加 classesN.odex 到 dexPathList.dexElements dexPathList->>DexFile: 完成 dex 加载
这里存在性能瓶颈有两个地方:
- 每个 Secondary dex 会创建对应的 zip 文件
- 通过 DexFile.loadDex 对 zip 文件做 dexopt,会做一次解压,并且 dexopt 非常耗时
BoostMultidex 核心思路就是避免启动时候 ODEX, 先直接加载原始 DEX 完成启动,再在后台服务进程完成 ODEX 优化,下次冷启动就可以使用 ODEX 的代码
BoostMultiDex 要点
通过官方的介绍,再加上阅读源码可以知道,BoostMultiDex
技术要点如下:
- 利用系统隐藏函数,直接加载原始 DEX 字节码,避免 ODEX 耗时
- 多级加载,在 DEX 字节码、DEX 文件、ODEX 文件中选取最合适的产物启动 APP
- 单独进程做 OPT,并实现合理的中断及恢复机制
BoostMultiDex 使用
使用的话也特别简单,跟官方的MultiDex
差不多
首先在引入依赖
1 | dependencies { |
其次在 Application.attachBaseContext 的最前面进行初始化即可:
1 | public class AppApplication extends Application { |
因为是大厂出品,在使用上其实没有过多的担忧,为防止意外发生,为此我还准备了一份设备白名单,如果 App 在这个设备上启动出错是因为引入BoostMultiDex
造成的,我会把这些设备的型号放到白名单里,让其使用官方的MultidDex
方案。最后通过几轮测试都没有发现问题,也就放心的在生产环境使用了。
总结
总体使用下来,优化效果还是蛮显著,Android 4.4
启动时几乎看不到黑屏了,默认主题图片也没有等待过长的时间。
继续探索 App 启动优化的话还有其他的方案,比如:
- Facebook 出品的ReDex
- Booster 库下
booster-r-inline
插件
这些后续再做研究吧。