应用的构建速度会直接影响开发效率,本文将带您通过改造一个 Android 应用: “Google 追踪圣诞老人 (Google Santa Tracker)” 来为大家提供十个小技巧,帮助提升应用的 Gradle 构建速度,当我们应用了所有的小技巧之后,该演示应用的构建速度快了三倍以上。
其次,在我们开启速度提升调优之前,来了解本次三个性能指标的说明:
-
全量构建,也就是重新开始编译整个工程的 debug 版;
-
代码增量构建,指的是我们修改了工程的 Java / Kotlin 代码;
-
资源增量构建,指的是我们对资源文件的修改,增加减少了图片和字符串资源等。
小技巧 1: 使用最新版本的 Android Gradle 插件
每次 Android Gradle 插件的更新都会修复大量的 bug 及提升性能等新特性,因此保持最新的 Android Gradle 插件版本有非常大的必要。
从 3.0 版本开始,我们将通过 google() 的 Maven 仓库分发新的 Android Gradle 插件,所以需要在 repositories 处加入 google() 以获得最新的插件更新 (现在的 Android Studio 新建工程的时候会默认加入 google() 的 Maven 仓库指向)。
这是将 Android Gradle 插件版本从 2.x 更新到 3.0.0-alpha1 之后得到的结果 (这里的演示是基于 3.0.0-alpha1 版本,随着插件版本的更新,性能的提升会更加明显),我们可以看出,全量构建一次应用的时间直接减少了 25%,代码改动的增量构建减少了将近 40%,资源改动的增量构建也减少了 16%。
小技巧 2: 避免激活旧版的 Multidex
启用 multidex https://developer.android.google.cn/studio/build/multidex.html
如果您是通过 Android Studio 的运行/调试按钮来执行构建,那么无需考虑这个问题,新版本的 Android Studio 会自动检测连接的设备和模拟器,如果系统的 API 级别大于 21 则进行原生的 multidex 支持,同时会忽略工程里对最低 API 级别 (minSdkVersion) 的设置。
这一次的性能改进结果效果也非常明显 (灰色的线条是最初的结果),在全量构建的时候我们又降低了 5.5 秒的时间,而在代码改动的增量构建里时间减少了 50% 以上,资源改动的增量构建与之前的时间相同。
小技巧 3: 禁用 Multiple APK 构建
禁用多 APK 构建不能仅仅在 splits 里设置,因为这里的设置对工程里所有的构建变体都是可见的。正确的禁用多 APK 构建的方法是创建一个属性来做判断,这里我们设置了一个名为 “devBuild” 的属性,在构建的过程中把这个值传给 gradle,此时 gradle 会将 splits.abi.enable 和 splits.density.enable 设置为 false,它就不会生成多个 APK 了。
在 Android Studio 里,您可以通过偏好设置,构建、执行和部署分类里,选择编译器选项来为命令行加入参数: -PdevBuild,这样每次在构建的时候 Android Studio 会把这个值传递给 gradle 以避免生成多个 APK。
如上图所示,这是我在禁用了多 APK 之后的效果,各项指标都在继续降低。
-
Multiple APK
https://developer.android.google.cn/google/play/publishing/multiple-apks.html
-
构建变体
https://developer.android.google.cn/studio/build/build-variants.html
小技巧 4: 最小化使用资源文件
这里我们看到了较大程度上的改观,全量构建的时间又降低了 6 秒,增量构建的时间也分别降低了 20% 以上。
小技巧 5: 禁用 PNG 压缩
如果要避免使用 PNG 压缩,我们可以在小技巧 3 里提到的,在 devBuild 属性里加入 aaptOptions.cruncherEnabled = false 来实现,在构建的过程中把这个值传给 gradle,它就可以避免执行 PNG 压缩命令了。
这可以看到全量构建又减少了 9 秒的时间,这也是因为 Google 追踪圣诞老人应用里有 3,500 多张 PNG 图片,这要花费大量的时间进行压缩计算,所以这方面的效率提升显得很明显,而其他增量构建只是维持了之前的情况。
小技巧 6: 使用 Apply Changes
从 Android Studio 3.5 版开始 (3.5 版目前在 Beta 构建渠道发布),开发者们可以使用 Apply Changes 功能来提高构建性能,它可以让代码和资源的改动直接生效而无需重启应用,有时候甚至无需重启当前的 Activity。与 Instant Run 的实现方式不一样,Apply Changes 充分利用了 Android 8.0 以上版本操作系统的特性进行运行时检测,从而动态的对类进行重新定义。因此,如果您希望使用 Apply Changes,则需要让您的工程运行在 Android 8.0 (API级别26) 以上的真机或者模拟器上。
小技巧 7: 避免被动的改动
这个例子里,我们故意在构建脚本中加入里一些捣乱的代码以展现其带来的损失。同时也举一个在使用 Crashlytics 时的实际例子,这个插件默认会为每次构建中都加入唯一 ID 作为构建标识,这会带来不必要的时间损失,您可以通过在构建脚本里加入 ext.alwaysUpdateBuildId = false 来避免这个,当然也可以选择在开发阶段完全关闭 Crashlytics。
小技巧 8: 不使用动态版本标识
Gradle 提供了一个非常方便的依赖库版本号管理功能,方便开发者们通过使用一个加号 “+” 标识希望使用这个依赖库的最新版本。但是使用动态版本有几个风险,从性能角度来说,Gradle 会每隔 24 小时去检查一次依赖库的更新,如果您的依赖库很多,而且都使用了动态获取最新版本的这个设定,那会对构建时候的性能产生一定的影响。
即使您不是特别在意这些性能损耗,但是它仍然是有风险的——依赖库的版本更新会让您的构建充满不确定性,可能两周之后您就在构建一个完全不一样的工程了,因为依赖库代码的更新对开发者们是不可见的。
小技巧 9: Gradle 内存分配调优
小技巧 10: 开启 Gradle 构建缓存
关于 Gradle 构建缓存 https://docs.gradle.org/current/userguide/build_cache.html
总结
代码仓库 https://github.com/jmslau/santa-tracker-android 官方文档 https://developer.android.google.cn/studio/build/optimize-your-build