hum*_*zed 899 dependency-management gradle transitive-dependency build.gradle gradle-plugin
在更新到Android Studio 3.0并创建一个新项目后,我注意到build.gradle有一种新方法可以添加新的依赖项,而不是compile存在implementation而不是testCompile存在testImplementation.
例:
implementation 'com.android.support:appcompat-v7:25.0.0'
testImplementation 'junit:junit:4.12'
Run Code Online (Sandbox Code Playgroud)
代替
compile 'com.android.support:appcompat-v7:25.0.0'
testCompile 'junit:junit:4.12'
Run Code Online (Sandbox Code Playgroud)
它们之间有什么区别,我应该使用什么?
hum*_*zed 1162
TL;博士
只需更换:
compile 同 implementationapi 同 testCompiletestImplementation 同 debugCompiledebugImplementation 同 androidTestCompileandroidTestImplementation仍然有效.它在3.0中添加以替换提供而不是编译.(compileOnly当Gradle没有该用例的配置名称并在Maven提供的范围之后命名它时引入.)这是谷歌在IO17宣布的 Gradle 3.0带来的重大变化之一.
该provided配置现已弃用,应替换为compile或implementation
从Gradle文档:
Run Code Online (Sandbox Code Playgroud)dependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.apache.commons:commons-lang3:3.5' }出现在
api配置中的依赖关系将传递给库的使用者,因此将出现在使用者的编译类路径中.
api另一方面,配置中的依赖关系不会暴露给消费者,因此不会泄漏到消费者的编译类路径中.这有几个好处:
- 依赖关系不再泄漏到消费者的编译类路径中,因此您永远不会意外地依赖于传递依赖
- 由于减少了类路径大小,编译速度更快
- 当实现依赖性发生变化时,重新编译的次数减少:消费者不需要重新编译
- 清理发布:当与新的maven-publish插件结合使用时,Java库会生成POM文件,这些文件准确区分编译库所需的内容以及在运行时使用库所需的内容(换句话说,不要混合编译库本身所需的内容以及编译库所需的内容.
编译配置仍然存在,但不应使用,因为它不提供
implementation和api配置提供的保证.
注意:如果您只在应用程序模块中使用库(常见情况),您将不会注意到任何差异.
如果您有一个复杂的项目,模块相互依赖,或者您正在创建一个库,那么您将只能看到差异.
ald*_*dok 322
这个答案将展示之间的差异implementation,api以及compile在一个项目.假设我有一个包含三个Gradle模块的项目:
app具有myandroidlibrary依赖性.myandroidlibrary具有myjavalibrary 依赖性.
app - > myandroidlibrary - > myjavalibrary
myjavalibrary有一MySecret节课
public class MySecret {
public static String getSecret() {
return "Money";
}
}
Run Code Online (Sandbox Code Playgroud)
myandroidlibrary有一个MyAndroidComponent类来操纵MySecret类的价值.
public class MyAndroidComponent {
private static String component = MySecret.getSecret();
public static String getComponent() {
return "My component: " + component;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,app只对价值感兴趣myandroidlibrary
TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());
Run Code Online (Sandbox Code Playgroud)
现在,我们来谈谈appbuild.gradle的依赖关系.它简单直观.:myandroidlibrary需要使用app
dependencies {
implementation project(':myandroidlibrary')
}
Run Code Online (Sandbox Code Playgroud)
但是,您认为implementationbuild.gradle应该是什么样子?我们应该使用哪个范围?
我们有三种选择:
dependencies {
// Option #1
implementation project(':myjavalibrary')
// Option #2
compile project(':myjavalibrary')
// Option #3
api project(':myjavalibrary')
}
Run Code Online (Sandbox Code Playgroud)
它们之间有什么区别,我应该使用什么?
编译和Api
如果你正在使用myandroidlibrary和compile.我们的Android应用程序现在能够访问api依赖项,这是一个myandroidcomponent类.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());
Run Code Online (Sandbox Code Playgroud)
履行
如果您正在使用MySecret配置,implementation则不会公开.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile
Run Code Online (Sandbox Code Playgroud)
那么,您应该选择哪种配置?这真的取决于你的要求.
如果要暴露依赖项使用,MySecret或者api,如果您不想公开依赖项(隐藏内部模块),则使用compile.
这只是Gradle配置的要点,请参阅表49.1.Java Library插件 - 用于声明依赖关系的配置以获得更详细的说明.
有关此答案的示例项目,请访问https://github.com/aldoKelvianto/ImplementationVsCompile
Ris*_*hav 61
Compile配置已弃用,应替换为implementation或api.
您可以在https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation上阅读文档.
简介部分是 -
标准Java插件和Java Library插件之间的主要区别在于后者引入了向消费者公开的API的概念.库是一个Java组件,旨在供其他组件使用.这是多项目构建中非常常见的用例,但只要您有外部依赖项.
该插件公开了两种可用于声明依赖关系的配置:api和实现.api配置应该用于声明由库API导出的依赖项,而实现配置应该用于声明组件内部的依赖项.
Sha*_*ani 43
简要解决方案
更好的方法是compile用implementation依赖项替换所有依赖项.只有泄漏模块接口的地方,才应该使用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'
})
}
Run Code Online (Sandbox Code Playgroud)
解释更多:
在Android Gradle插件3.0之前:我们遇到了一个很大的问题,即一个代码更改导致所有模块被重新编译.造成这种情况的根本原因是Gradle不知道您是否通过另一个模块泄漏模块的接口.
在Android Gradle插件3.0之后:最新的Android Gradle插件现在要求您明确定义是否泄漏模块的界面.基于此,它可以在应该重新编译的内容上做出正确的选择.
因此,compile依赖项已被弃用,取而代之的是两个新的依赖项:
api:您通过自己的接口泄漏此模块的接口,这意味着与旧的compile依赖项完全相同
implementation:您只在内部使用此模块,不会通过您的界面泄漏它
因此,如果已使用模块的接口发生变化,您现在可以明确告诉Gradle重新编译模块.
由Jeroen Mols博客提供
yoA*_*ex5 19
Gradle 依赖配置
Gradle 3.0 引入了下一个变化:
compile -> api
api关键字与deprecated 相同,compile它为所有级别公开此依赖项
compile -> implementation
是可取的方式,因为有一些优点。implementation仅在构建时公开上一级的依赖项(依赖项在运行时可用)。因此,您的构建速度更快(无需重新编译高于 1 级的消费者)
provided -> compileOnly
此依赖项仅在编译时可用(该依赖项在运行时不可用)。这种依赖不能是可传递的,并且是.aar。它可以与编译时注释处理器[About]一起使用,并允许您减少最终输出文件
compile -> annotationProcessor
非常类似于compileOnly但也保证传递依赖对消费者不可见
apk -> runtimeOnly
依赖在编译时不可用,但在运行时可用。
Waj*_*Ali 11
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| Name | Role | Consumable? | Resolveable? | Description |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| api | Declaring | no | no | This is where you should declare |
| | API | | | dependencies which are transitively |
| | dependencies | | | exported to consumers, for compile. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| implementation | Declaring | no | no | This is where you should |
| | implementation | | | declare dependencies which are |
| | dependencies | | | purely internal and not |
| | | | | meant to be exposed to consumers. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| compileOnly | Declaring compile | yes | yes | This is where you should |
| | only | | | declare dependencies |
| | dependencies | | | which are only required |
| | | | | at compile time, but should |
| | | | | not leak into the runtime. |
| | | | | This typically includes dependencies |
| | | | | which are shaded when found at runtime. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| runtimeOnly | Declaring | no | no | This is where you should |
| | runtime | | | declare dependencies which |
| | dependencies | | | are only required at runtime, |
| | | | | and not at compile time. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testImplementation | Test dependencies | no | no | This is where you |
| | | | | should declare dependencies |
| | | | | which are used to compile tests. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testCompileOnly | Declaring test | yes | yes | This is where you should |
| | compile only | | | declare dependencies |
| | dependencies | | | which are only required |
| | | | | at test compile time, |
| | | | | but should not leak into the runtime. |
| | | | | This typically includes dependencies |
| | | | | which are shaded when found at runtime. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| testRuntimeOnly | Declaring test | no | no | This is where you should |
| | runtime dependencies | | | declare dependencies which |
| | | | | are only required at test |
| | | | | runtime, and not at test compile time. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
Run Code Online (Sandbox Code Playgroud)
由于版本 5.6.3 Gradle 文档提供了简单的经验法则来确定是否应将旧compile依赖项(或新依赖项)替换为implementation或api依赖项:
- 在可能的情况下更喜欢
implementation配置api这使依赖项远离使用者的编译类路径。此外,如果任何实现类型意外泄漏到公共 API 中,消费者将立即无法编译。
那么什么时候应该使用
api配置呢?API 依赖项至少包含一种在库二进制接口中公开的类型,通常称为其 ABI(应用程序二进制接口)。这包括但不限于:
- 超类或接口中使用的类型
- 公共方法参数中使用的类型,包括泛型参数类型(其中公共是编译器可见的东西。即 Java 世界中的公共、受保护和包私有成员)
- 公共领域使用的类型
- 公共注释类型
相比之下,以下列表中使用的任何类型都与 ABI 无关,因此应声明为
implementation依赖项:
- 专门用于方法体的类型
- 专用于私有成员的类型
- 仅在内部类中找到的类型(Gradle 的未来版本将允许您声明哪些包属于公共 API)
小智 7
外行用语的简要区别是:
阅读@aldok的答案以获取完整示例。
继续之前的一些注意事项;compile 已被弃用,文档说明您应该使用实现,因为 compile 将在 Gradle 7.0 版中删除。如果您运行 Gradle 构建,--warning-mode all您将看到以下消息;
已弃用依赖声明的编译配置。这将在 Gradle 7.0 中失败并出现错误。请改用实现配置。
仅通过查看帮助页面中的图像,就很有意义。
所以你有蓝色的盒子compileClasspath和runtimeClassPath。
这compileClasspath是在运行gradle build. 编译时将出现在类路径上的库将是在您的 gradle 构建中使用compileOnly或配置的所有库implementation。
然后我们有了runtimeClasspath,那些都是您使用implementation或添加的包runtimeOnly。所有这些库都将添加到您部署在服务器上的最终构建文件中。
正如您在图像中看到的,如果您希望一个库既用于编译,又希望将其添加到构建文件中,则implementation应该使用它。
一个例子runtimeOnly可以是数据库驱动程序。
一个例子compileOnly可以是 servlet-api。
一个例子implementation可以是 spring-core。
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
| 归档时间: |
|
| 查看次数: |
274385 次 |
| 最近记录: |