亚游娱乐 - 加快Gradle的构建速度

${website.getHeaderOriginal(${article.taxonomyName})}


北京时间7月19日下午消息··|,唯品会股价周三盘前大涨近8%··|,此前消息称··|,京东与唯品会均否认合并··|--。7月19日··|,有媒体报道称··|,京东正在和唯品会秘密谈判收并购事宜··|,并已经进行到实质阶段··|--。唯品会副总裁黄红英在接受21世纪经济报道记者采访时称··|,该消息纯属谣言··|,并不属实··|--。随后··|,京东公司相关人士也否认了上述消息··|--。

本篇来自 Halohoop 的投稿··|, 向大家分享了加快gradle构建速度··|,是对gradle效率提高教程··|,希望大家喜欢··|--。

Halohoop 的博客地址:

http://halohoop.com

AS 中 gradle 构建一般可以分为三种:

  1. 从0开始构建··|,Full Build;

  2. 修改源代码后构建··|,之前构建过··|,Incremental build java change;

  3. 修改资源文件后构建··|,之前构建过··|,Incremental build resource change··|--。

从这三方面其实都可以有切入点来进行提速··|,gradle 插件 3.0 做了大改··|,优化了很多东西··|,包括 gradle 依赖系统以及缓存系统··|,这些都是直接影响构建速度的因素··|,整理了有10+个小技巧可以加快我们的构建速度··|,下面请听我一一道来··|--。

技巧1:使用最新版本的 gradle 插件

看到 google.com 之后··|,相信你应该知道要拿个“梯子”的··|,所以我说升级 as 最方便嘛··|,而现在 gradle 的版本已经更新到 alpha1+了(现在是2017年06月12日)··|,根据谷歌官方只要是3.0+··|,也就是以 2017 I/O 大会的版本开始就可以··|--。

技巧2:避免使用legacy multidex

当 app 方法数量超过64k的时候就会编译失败··|,早期版本的构建系统按如下方式报告这一错误: 

较新版本的 Android 构建系统虽然显示的错误不同··|,但指示的是同一问题:

使用 multidex 分包处理是谷歌官方给我们提供的解决方案··|,由于分包被内置支持在5.0以及之后··|,当我们需要兼容的版本跨越 5.0 也就是 api21 的时候··|,比如说14–23··|,那么我们需要使用兼容库:

com.android.support:multidex:1.0.0

使用兼容库能让我们的低版本的也进行分包处理··|,参考:

https://developer.android.com/studio/build/multidex.html#about

因为具体如何操作 gradle 需要配置什么 Application 需要如何设置等不是本文重点··|,请各位自行谷歌、百度··|--。

根据谷歌官方描述··|,使用兼容库会明显拖慢构建··|,也就是如果你的调试机器版本低于5.0··|,又进行了分包处理··|,那么当你点击那个绿色构建按钮▶或者使用命令行 gradlew 构建的时候··|,那你可以先去吃一顿饭先了(Just kidding!)··|--。

所以我们在开发调试的时候尽量使用高版本的手机 5.0+··|,等功能完成了··|,后面做兼容低版本的时候再使用低版本的手机进行调试··|--。可能有人会说··|,我在开发功能的时候如果不实时调试低版本的兼容问题后期可能有问题··|,关于这一点··|,我想说的是一点是经验问题··|,经验足的人就是能够知道你这段代码写出来可能的结果··|,这是内功··|,不可言状··|,却又确实存在的能力··|,我见过这样的人··|,你没写出来他就能够知道运行的结果··|,另一点是我们需要相信google 的兼容团队给我们的兼容方案是能够解决绝大部分的兼容问题的··|,我指的兼容方案是指使用 appcompat、support 等之类的兼容库··|--。

技巧3:关闭multi apk

如果你的项目需要编译出多个density或者多个abi(CPU架构)的APK··|,那么这也是开发构建的时候不需要做的操作··|,因为在你手上调试的机器只是一种density一种abi··|,因此我们在构建的时候可以将 multi-apk··|,地址如下:

https://developer.android.com/studio/build/configure-apk-splits.html

的构建给去除··|--。可以进行如下配置:

但是显然这趟配置影响全局配置··|,后期还可能忘记改回来··|,更灵活一点的方式可以这样:

或者··|,可以更加细致一点:

注意 project 没有 s··|,不是 projects··|--。并且这个判断的代码必须置于 splits 块的下面··|,否则就可能设置完之后就又被覆盖回来了··|--。
“HaloDevBuild” 属性的字符串我们可以自定义··|,在 gradle 写好这个判断之后··|,我们就可以在命令行编译了··|,命令如下:

比如:

又或者可以构建顺带安装了:

-P 之后表示要传递的属性··|--。当然我们如果需要在as中点击绿色构建按钮▶编译··|,那就要设置一下每次都要传入属性:

另外··|,我们可以这样获取 Android 手机 CPU/ABI 型号:

技巧4:使用最少的资源打包

和上面的思路一样··|,我们开发调试的时候只需要用到一种语言和一套资源文件··|--。所以我们打包的时候不需要将所有的东西都放到这个调试的 apk 中··|--。我们可以采用定义变体的方式来完成··|,地址如下:

https://developer.android.com/studio/build/build-variants.html

注意下面的 resConfigs 属性指定了要保留的素材资源文件和语言资源文件··|--。

技巧5:关闭 aapt 对 png 的优化

aapt 打包时候对资源图片的处理也会耗时··|,这里主要针对 PNG··|,我们可以暂时关闭这种处理··|,还是用到上面的技巧··|,gradle 配置如下:

当然如果我们将 PNG 转为 webP 也可以是一种优化方案··|--。as2.3+ 支持直接转换··|,右键直接 png 图片选则 convert to webP··|--。当然 webP 是有版本要求的··|,所以请注意其用法··|,非本文重点自行百度了解··|--。

技巧6:使用 instant run

多使用 instant run··|,根据谷歌的描述··|,as3.0和2.0的 instant run 有巨大的差别··|,做了很多的优化··|,instant run 要求调试的机器必须要在api21或者以上··|,而不是你的项目最小版本要在21或者以上··|--。还有一点就是使用 instant run 的时候··|,如果我们首次构建是从0开始的··|,那么会比不使用 instant run 慢一点··|,因为需要为后面的 instant run 的冷热交换去准备一些额外的东西··|,然而如果后面一直都使用 instant run··|,那么首次构建的延缓的时间就能很快被挽回来··|--。

技巧7:避免写一些不必要的更改

有些开发者为了方便会直接使用时间戳来作为每次构建的版本号(或者是自己的一套计算算法)··|,像这样:

这个一定程度上方便了我们··|,但是对于 gradle 构建系统来说··|,这不是好事··|--。由于每次版本号都有修改··|,这就直接导致清单文件 Manifest 的更改··|--。而清单文件的修改势必会趋势构建系统重新审视整个项目情况··|,这会增加很多额外的时间··|,这在开发调试的时候根本没有必要··|--。

还是利用上面的技巧··|,我们可以这样:

技巧8:类库不要使用动态的版本

项目中可能会这样配置:

这个加号+··|,导致 gradle 每次构建都要检查新的版本··|--。即使你希望每次都用最新但是还是不好··|,因为库可能已经有很大的变化了··|,但是你是基于旧版开发的··|,所以为了安全不要这样设置··|--。其实这和我们 coding 还是一样的道理··|,我们码代码的时候肯定会考虑如何能让别人的修改不影响到我们自己的··|,因此这个加号使不得··|,使不得··|--。

技巧9:查看jvm使用的内存是否合适

我一般设置为2g··|,这个根据项目的不同可能会有不同效果··|,所以可以试着稍微调整一下··|--。

技巧10:打开 gradle 新的缓存机制

我们可以通过一个设置使用这种新的缓存机制··|,如下:

文章开头也提到过··|,Gradle 3.5(现在20170612的gradle版本已经4.0了)新的机制··|,可以缓存所有任务的输出··|--。这个和 as2.3 时候介绍的 build 缓存不一样··|,build 缓存只缓存预 dex 的外部 libs··|--。而任何时候的构建缓存其实都是可复用的··|,比如切换分支之后··|,还可以用其他分支时候的构建缓存··|--。

当然··|,根据谷歌官方描述··|,这个设置的背后还有很多需要完善的地方··|,使用的同时··|,我们可以有更多后期优化的期待··|--。

技巧11:使用新的依赖机制

按照官方的描述··|,gradle3.0 之前··|,构建系统的依赖关系被认为是一种完全错误的方式··|,举一个例子:

app 依赖了库 libX··|,库 libX又依赖库 libY··|--。

app:

compile 'libX'

libX:

compile 'libY'

如果在 app 中调用了 libY 的方法··|,这个时候如果 libY 中的方法做了改变··|,那么由于 libY 被和 libX 和 app 都有依赖被依赖关系··|,这时候如果构建 libY 势必会导致 libX 和 app 也重新构建··|--。

这应该是个完全错误的依赖方式··|,正确的方式应该是既然 app 只依赖了 libX 那就不应该知道 libY 中的 api··|,然而这在构建系统3.0(gradle 插件)之前都是这样存在的··|,因此 3.0 做了改变··|,引入了新的依赖形式··|,api 和 implementation 来替换 compile··|--。

  • implementation:表示我依赖你··|,但是你的 api 不会被我重新分享出去了··|--。

  • api:表示我依赖你··|,但是你的 api 会被我重新分享出去了

那么在看上面的例子就变成了:

app:

implementation 'libX'

libX:

api 'libY'

由于存在之前的这种依赖传递的错误机制··|,因此我们项目中很可能就出现了这种依赖传递之后导致一个小修改就把所有库都构建一遍的情况··|,因此我们花一些时间将一些库的compile 都替换成 api 和 impementation 对我们是有好处的··|,一来有效缩短构建时间··|,而来真正搞清楚项目中依赖的情况··|,那些 api 需要依赖传递··|,哪些不需要··|--。

当然我们还是可以继续使用 compile··|,不过这种方式已经是过时的了··|,我们只要更新了最新插件··|,那么新建了项目就会发现所有的 compile 都会被换成了 implementation··|--。相关的修改还有 androidTestImplementation 和 testImplementation··|,对应的是原来的androidTestCompile 和 testCompile··|--。

根据上述技巧··|,我写了一个小 demo:

https://github.com/halohoop/SpeedUpGradleBuild2

Stay hungry stay foolish!

每天学习累了··|,看些搞笑的段子放松一下吧··|--。关注最具娱乐精神的公众号··|,每天都有好心情··|--。

如果你有好的技术文章想和大家分享··|,欢迎向我的公众号投稿··|,投稿具体细节请在公众号主页点击“投稿”菜单查看··|--。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

${website.getFooterOriginal(${article.taxonomyName})}

发布者 :亚游娱乐_亚游娱乐官网_ag亚游娱乐平台 - 分类 ag亚游娱乐真人平台

(必填)