在更新到Android Studio 3.0并创建一个新项目后,我注意到在构建中。gradle有一种新方法来添加新的依赖项,而不是compile,而是implementation,而不是testCompile,而是testimplemimplementation。
例子:
implementation 'com.android.support:appcompat-v7:25.0.0'
testImplementation 'junit:junit:4.12'
而不是
compile 'com.android.support:appcompat-v7:25.0.0'
testCompile 'junit:junit:4.12'
它们之间的区别是什么,我应该用什么?
implementation: mostly we use implementation configuration. It hides the internal dependency of the module to its consumer to avoid accidental use of any transitive dependency, hence faster compilation and less recompilation.
api: must be used very carefully, since it leaks the to consumer’s compile classpath, hence misusing of api could lead to dependency pollution.
compileOnly: when we don’t need any dependency at runtime, since compileOnly dependency won’t become the part of the final build. we will get a smaller build size.
runtimeOnly: when we want to change or swap the behaviour of the library at runtime (in final build).
我已经创建了一个深入了解每个工作示例的帖子:源代码
https://medium.com/@gauraw.negi/how-gradle-dependency-configurations-work-underhood-e934906752e5
简单的解决方案:
更好的方法是用实现依赖替换所有编译依赖。只有在泄露模块接口时,才应该使用api。这应该会减少大量的重新编译。
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:25.4.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
// …
testImplementation 'junit:junit:4.12'
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
}
解释:
在Android Gradle插件3.0之前:我们遇到了一个大问题,即一个代码更改导致所有模块被重新编译。造成这种情况的根本原因是Gradle不知道你是否通过另一个模块泄露了一个模块的接口。
在Android Gradle插件3.0之后:最新的Android Gradle插件现在要求你显式定义是否泄露了模块的接口。在此基础上,它可以对应该重新编译的内容做出正确的选择。
因此,compile依赖项已被弃用,并被两个新的依赖项所取代:
Api:你通过你自己的接口泄露了这个模块的接口,这意味着和旧的编译依赖完全一样
实现:你只在内部使用这个模块,不会通过你的接口泄露它
所以现在你可以显式地告诉Gradle重新编译一个模块,如果使用的模块的接口改变与否。
由Jeroen Mols博客提供
从版本5.6.3开始,Gradle文档提供了简单的经验规则来识别旧的编译依赖项(或新的依赖项)是否应该用一个实现或api依赖项替换:
Prefer the implementation configuration over api when possible
This keeps the dependencies off of the consumer’s compilation classpath. In addition, the consumers will immediately fail to compile if any implementation types accidentally leak into the public API.
So when should you use the api configuration? An API dependency is one that contains at least one type that is exposed in the library binary interface, often referred to as its ABI (Application Binary Interface). This includes, but is not limited to:
types used in super classes or interfaces
types used in public method parameters, including generic parameter types (where public is something that is visible to compilers. I.e. , public, protected and package private members in the Java world)
types used in public fields
public annotation types
By contrast, any type that is used in the following list is irrelevant to the ABI, and therefore should be declared as an implementation dependency:
types exclusively used in method bodies
types exclusively used in private members
types exclusively found in internal classes (future versions of Gradle will let you declare which packages belong to the public API)