Gralde 4.0 里程碑版本作为gradle的编译版本,该版本gradle编译速度有所加速,更加欣喜的是,完全支持Java8。当然,对于Kotlin的支持,在这个版本也有所体现,Kotlin插件默认是安装的。、
在com.android.tools.build:gradle 3.0 以下版本依赖在gradle 中的声明写法
compile fileTree(dir: 'libs', include: ['*.jar'])
- 1
但在3.0后的写法为
implementation fileTree(dir: 'libs', include: ['*.jar'])
或
api fileTree(dir: 'libs', include: ['*.jar'])
- 1
- 2
- 3
在3.0版本中,compile 指令被标注为过时方法,而新增了两个依赖指令,一个是implement 和api,这两个都可以进行依赖添加,但是有什么区别呢?
api 指令
完全等同于compile指令,没区别,你将所有的compile改成api,完全没有错。
implement指令
这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。
Implementation 变化
当本module依赖的ib(也可以是module)发生变化时,由于本module对外暴露的接口并不发生变化,在构建工程时gradle将会只重新编译本module,所有依赖于本module的module并不会发生编译。这种情况是没什么问题的。如图所示。
-
ABI变化
当本module依赖的ib(也可以是module)发生变化时,本module向外暴露的接口发生了变化,那么所有直接依赖于本module的module将不得不重新编译。
接下来,这些上层module可能通过其本身的接口对外暴露了底层module的部分内容,即意味着本module暴露的接口也发生了变化,这会使得依赖于上层module的上上层module也需要重新编译。这就导致了一个连锁效应,因此,为了绝对的安全起见,gradle将不得不重新编译整个工程,使得编译时间变得较长。如图所示。
那么重点来了:一点代码的改动可能会引起整个工程的重新编译,这将是多么悲催,而实际上我们之前的gradle插件2.0版本系列的确如此,根本原因就是gradle压根不知道暴露的接口可以通过一个接一个的依赖传递影响整个工程。
- Android Gradle plugin 3.0带来了解决方案
最新版的Gradle plugin需要你指出一个module的接口是否对外暴露其依赖lib的接口。基于此,可以让项目构建时,gradle可以判断哪个需要重新编译。因此,老版本的构建关键字compile被废弃了,而是改成了这两个: - api:同compile作用一样,即认为本module将会泄露其依赖的module的内容。
- implementation:本module不会通过自身的接口向外部暴露其依赖module的内容。
由此,我们可以明确的告诉gradle去重新编译一个module,若是这个使用的module的接口发生变化的话。
dependencies {
//当legofy接口发生变化时,需要重新编译本module以及所有使用本module的module
api project(':legofy')
// 仅当landscapevideocamera发生变化时,重新编译本module
implementation project(':landscapevideocamera:1.0.0')
}
- 1
- 2
- 3
- 4
- 5
- 6
- 迁移指南
理论上,你可以将原来工程中的compile完全替换为现在的api,但是一旦依赖发生变化,将会使所有的module重新编译,造成编译过长。
所以更好的方式就是使用implementation来进行依赖,这会大大改善工程的构建时间。只有你明确要向外部暴露所依赖lib的接口时,才需要使用api依赖,整体来说,会减少很多重新编译。这一点,在官方指南中说的比较明确。
- 其它的变化
既然有了比较大的改变,索性官方团队利用此机会改了更多配置属性的名字,
比如provided改成了compileOnly,apk改成了runtimeOnly