Android 应用构建速度提高的十个小技巧

应用的构建速度会直接影响开发效率,本文将带您经过改造一个 Android 应用: “Google 追踪圣诞老人 (Google Santa Tracker)” 来为你们提供十个小技巧,帮助提高应用的 Gradle 构建速度,当咱们应用了全部的小技巧以后,该演示应用的构建速度快了三倍以上。
html


首先来了解一下 “Google 追踪圣诞老人” 应用的工程背景: 这个应用有约 60M 大小,它包含 9 个模块,有 500 多个 Java 文件,1,700 多个 XML 文件、3,500 多张 PNG 图片资源,用到了 Mutil-dex,没有注解处理器。


其次,在咱们开启速度提高调优以前,来了解本次三个性能指标的说明:java

  • 全量构建,也就是从新开始编译整个工程的 debug 版;android

  • 代码增量构建,指的是咱们修改了工程的 Java / Kotlin 代码;git

  • 资源增量构建,指的是咱们对资源文件的修改,增长减小了图片和字符串资源等。github



每一个小技巧实施之后,咱们会对好比上三个场景的构建时间以做为咱们的量化标准。请注意,因为工程规模大小不1、开发环境各异,开发者们在实际的操做中的结果可能会与本文的结果有所不一样。





小技巧 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%。app




小技巧 2: 避免激活旧版的 Multidexide




这个小技巧你们应该比较熟悉——避免激活旧版的 multidex。当您的应用配置方法数超过 64K 的时候,须要 启用 multidex 。当启用了 multidex,且工程的最低 API 级别在 21 以前时,旧版的 multidex 就会被激活,这将严重拖慢您的构建速度,缘由是 21 以前的 API 级别并无原生的支持 multidex。



  • 启用 multidex
    https://developer.android.google.cn/studio/build/multidex.html





若是是经过 Android Studio 的运行/调试按钮来执行构建,那么无需考虑这个问题,新版本的 Android Studio 会自动检测链接的设备和模拟器,若是系统的 API 级别大于 21 则进行原生的 multidex 支持,同时会忽略工程里对最低 API 级别 (minSdkVersion) 的设置。

习惯经过命令行窗口构建工程的开发者们则须要试着避免这个问题: 配置一个新的 productFlavor,设定工程的最低 API 级别为 21 或者以上,在命令行里调用 assembleDevelopmentDebug 便可避免这个问题。



这一次的性能改进结果效果也很是明显 (灰色的线条是最初的结果),在全量构建的时候咱们又下降了 5.5 秒的时间,而在代码改动的增量构建里时间减小了 50% 以上,资源改动的增量构建与以前的时间相同。





小技巧 3: 禁用 Multiple APK 构建性能




在应用须要发布和上架的时候,咱们每每会使用 “ Multiple APK ” 构建,它能够根据 ABI 和像素密度建立不一样版本的应用,使包体积下降等。但这个在开发阶段彷佛显得有些多余,因此咱们须要禁用多 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: 最小化使用资源文件




的应用包含大量本地化资源或者为不一样像素密度加入了特别的资源时,可能须要应用这个小技巧来提升构建速度——最小化开发阶段打包进应用的资源数量。

构建系统默认会将声明过或者使用过的资源所有打包进 APK,但在开发阶段咱们可能只用到了其中一套而已,针对这种状况,咱们须要使用 resConfigs() 来指定构建开发版本时所须要用到的资源,如语言版本和屏幕像素密度。


这里咱们看到了较大程度上的改观,全量构建的时间又下降了 6 秒,增量构建的时间也分别下降了 20% 以上。




小技巧 5: 禁用 PNG 压缩




与小技巧 4 同样,这个特性自己在打包发布阶段是至关有帮助的—— PNG 压缩,但在开发阶段禁用这个功能能够提升构建效率。默认状况下,AAPT 会压缩工程的 PNG 资源以减少 APK 体积,根据图片的数量和大小,这个过程所消耗的时间有长有短。



若是要避免使用 PNG 压缩,咱们能够在小技巧 3 里提到的,在 devBuild 属性里加入 aaptOptions.cruncherEnabled = false 来实现,在构建的过程当中把这个值传给 gradle,它就能够避免执行 PNG 压缩命令了。



另一个避免压缩 PNG 的方法是使用把 PNG 转换成 WebP 格式的图片,对比 PNG 格式,WebP 能够减小最多 25% 的大小,同时 2.3 以上版本的 Android Studio 直接支持 PNG 到 WebP 格式的转换。

须要注意的是,API 级别 15 及更高能够支持不透明的 WebP 格式图片,若是是透明格式的 WebP,须要 API 级别 18 以及更高。



这能够看到全量构建又减小了 9 秒的时间,这也是由于 Google 追踪圣诞老人应用里有 3,500 多张 PNG 图片,这要花费大量的时间进行压缩计算,因此这方面的效率提高显得很明显,而其余增量构建只是维持了以前的状况。

特别提出一下关于 APK 体积的问题——对比了启用和禁用 PNG 压缩以后的 APK 体积以后,咱们发现先后的体积并无太大改变,这说明该工程里使用的 PNG 图片在导入以前已经通过了充分优化,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: 避免被动的改动




咱们经过一个很小的例子来讲明这个小技巧: 咱们把工程的版本号设定为基于当前时间的数字 (实际上你们应该不会这么操做),这样的结果是每次构建的时候版本号都是新的,工程的清单文件会所以发生改变,最后带来的结果就是拖慢了本次的构建速度。
如图所示,咱们发现增量构建的时间甚至增长了一倍,所以尽可能不要在构建脚本里加入太多无心义的内容。
解决这个问题并不难,咱们能够经过在构建脚本里判断是否有 devBuild 标记,若是有的话,咱们就把版本号设置为一个固定值就能够了。


这个例子里,咱们故意在构建脚本中加入里一些捣乱的代码以展示其带来的损失。同时也举一个在使用 Crashlytics 时的实际例子,这个插件默认会为每次构建中都加入惟一 ID 做为构建标识,这会带来没必要要的时间损失,能够经过在构建脚本里加入 ext.alwaysUpdateBuildId = false 来避免这个,固然也能够选择在开发阶段彻底关闭 Crashlytics。




小技巧 8: 不使用动态版本标识





Gradle 提供了一个很是方便的依赖库版本号管理功能,方便开发者们经过使用一个加号 “+” 标识但愿使用这个依赖库的最新版本。可是使用动态版本有几个风险,从性能角度来讲,Gradle 会每隔 24 小时去检查一次依赖库的更新,若是的依赖库不少,并且都使用了动态获取最新版本的这个设定,那会对构建时候的性能产生必定的影响。


即便不是特别在乎这些性能损耗,可是它仍然是有风险的——依赖库的版本更新会让的构建充满不肯定性,可能两周以后就在构建一个彻底不同的工程了,由于依赖库代码的更新对开发者们是不可见的。




小技巧 9: Gradle 内存分配调优




默认的构建环境里,咱们会给 Gradle 分配 1.5G 的内存,但这个并不是适用于全部的项目,须要经过对这个数字对调优来获得适合工程的最佳 Gradle 内存分配。




与此同时,从 Android Gradle 插件 2.1 版本以后,dex 已经默认在进程里了,因此若是以前设定过 javaMaxHeapSize 值,能够选择删掉它了。





小技巧 10: 开启 Gradle 构建缓存




Gradle 新推出的缓存机制效果很是出色,咱们建议你们尝试开启,最新的 Gradle 支持了 Kotlin 项目使用构建缓存,构建速度能够提升不少。Gradle 的构建缓存默认是不开启的,能够经过在命令行里加入 --build-cache 参数或者在工程根目录的 gradle.properties 里加入 org.gradle.caching=true 为全部人启用构建缓存。能够在这个文档里了解更多 关于 Gradle 构建缓存 的内容。



  • 关于 Gradle 构建缓存
    https://docs.gradle.org/current/userguide/build_cache.html






总结




在实践了全部的速度提高小技巧以后,获得的总体的改善结果,全量构建的速度比以前快了三倍以上,而代码改动的增量构建则快了 12 倍以上,咱们在 GitHub 上建立了一个 代码仓库 ,你们能够下载并实践一下咱们今天所提到的构建速度提高的技巧。更多关于如何提升应用构建速度的内容,请关注咱们的 官方文档



  • 代码仓库
    https://github.com/jmslau/santa-tracker-android
  • 官方文档
    https://developer.android.google.cn/studio/build/optimize-your-build



推荐阅读





本文分享自微信公众号 - Android群英传(android_heroes)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索