Vip*_*pha 183 implementation dependencies android gradle
我正在试图弄清楚构建我的依赖项时有什么区别api和implementation配置.
在文档中,它说implementation有更好的构建时间,但是,在类似的问题中看到这个 评论我想知道它是否属实.
由于我不是gradle的专家,我希望有人可以提供帮助.我已经阅读了文档,但我想知道一个易于理解的解释.
Mat*_*Pag 337
compile不推荐使用Gradle 关键字,而使用api和implementation关键字来配置依赖关系.
使用api是使用过时的等同compile,因此,如果您更换所有compile与api一切都将一如既往的作品.
要了解implementation关键字,请考虑以下示例.
例
假设您有一个名为的库MyLibrary,它在内部使用另一个名为的库InternalLibrary.像这样的东西:
// 'InternalLibrary' module
public class InternalLibrary {
public static String giveMeAString(){
return "hello";
}
}
Run Code Online (Sandbox Code Playgroud)
// 'MyLibrary' module
public class MyLibrary {
public String myString(){
return InternalLibrary.giveMeAString();
}
}
Run Code Online (Sandbox Code Playgroud)
假设MyLibrary build.gradle使用api配置dependencies{}如下:
dependencies {
api project(':InternalLibrary')
}
Run Code Online (Sandbox Code Playgroud)
您希望MyLibrary在代码中使用,因此在您的应用中build.gradle添加此依赖项:
dependencies {
implementation project(':MyLibrary')
}
Run Code Online (Sandbox Code Playgroud)
使用api配置(或已弃用compile),您可以访问InternalLibrary和MyLibrary应用程序代码:
// Access 'MyLibrary' (granted)
MyLibrary myLib = new MyLibrary();
System.out.println(myLib.myString());
// Can ALSO access the internal library too (and you shouldn't)
System.out.println(InternalLibrary.giveMeAString());
Run Code Online (Sandbox Code Playgroud)
通过这种方式,该模块implementation可能会"泄漏"某些内部实现.您不应该(能够)使用它,因为它不是由您直接导入的.
该implementation引入的配置,以防止这一点.所以,现在,如果你使用api的,而不是MyLibrary在InternalLibrary.giveMeAString():
dependencies {
implementation project(':InternalLibrary')
}
Run Code Online (Sandbox Code Playgroud)
在你的应用程序中InternalLibrary:
// 'InternalLibrary' module
public class InternalLibrary {
public static String giveMeAString(){
return "hello";
}
}
Run Code Online (Sandbox Code Playgroud)
您将无法再使用MyLibrary应用代码.
请注意,如果InternalLibrary用于compile导入implementation,您的应用将能够api毫无问题地进行呼叫,而无需使用implementation或compile添加api到您的应用.
这种装箱策略允许Android Gradle插件知道如果您编辑某些内容implementation以api仅触发重新编译而不会触发整个应用程序的重新编译,因为您无权访问compile.
当你有很多嵌套依赖项时,这种机制可以大大加快构建速度.(观看最后链接的视频,以便全面了解这一点)
结论
当您切换到新的Android插件摇篮3.XX,则应更换所有compile与api关键字(1*) .然后尝试编译和测试您的应用程序.如果一切正常,请保留代码,如果您遇到问题,可能是您的依赖项有问题,或者您使用了现在是私有且无法访问的内容.Android Gradle插件工程师Jerome Dochez的建议(1)*)
如果您是库管理员,则应该使用库implementation的公共API所需的每个依赖项,同时MyLibrary用于最终用户不能使用的测试依赖项或依赖项.
有用的文章展示了实现和api之间的区别
参考文献 (这是为节省时间而拆分的视频)
Google I/O 2017 - Gradle如何加速构建(完整视频)
Google I/O 2017 - Gradle如何加速构建(仅限新版PLADIN 3.0.0部分)
Google I/O 2017 - Gradle的构建速度(参考1*)
dev*_*max 86
我喜欢将api依赖关系视为公共(通过其他模块看到),而将implementation依赖关系视为私有(仅由此模块看到).
注意,与public/ privatevariables和方法不同,api/ implementationdependencies不是由运行时强制执行的.这只是一个构建时优化,它允许Gradle在其中一个依赖项更改其API时知道需要重新编译的模块.
小智 19
请参考链接:Android Studio 依赖配置,可在 android 开发者的官方网站上找到。
在依赖项块内,您可以使用几种不同的依赖项配置之一(例如上面显示的实现)来声明库依赖项。每个依赖项配置都为 Gradle 提供了有关如何使用依赖项的不同说明。
Gradle 将依赖项添加到编译类路径并将依赖项打包到构建输出。但是,当您的模块配置实现依赖项时,它会让 Gradle 知道您不希望该模块在编译时将依赖项泄漏给其他模块。也就是说,依赖关系仅在运行时可供其他模块使用。使用此依赖项配置而不是 api 或编译(已弃用)可以显着缩短构建时间,因为它减少了构建系统需要重新编译的模块数量。例如,如果实现依赖项更改了其 API,Gradle 只会重新编译该依赖项以及直接依赖于它的模块。大多数应用程序和测试模块应使用此配置。
Gradle 将依赖项添加到编译类路径和构建输出中。当模块包含 api 依赖项时,它会让 Gradle 知道该模块想要将该依赖项传递导出到其他模块,以便它们在运行时和编译时都可用。此配置的行为就像编译(现已弃用),但您应该谨慎使用它,并且仅与需要传递导出到其他上游使用者的依赖项一起使用。这是因为,如果 api 依赖项更改了其外部 API,Gradle 会在编译时重新编译有权访问该依赖项的所有模块。因此,拥有大量 api 依赖项会显着增加构建时间。除非您想将依赖项的 API 公开给单独的模块,否则库模块应该使用实现依赖项。
kol*_*bok 12
api关于vs的另一项技术说明implementation。假设您有以下依赖项:
dependencies {
api "com.example:foo:1.0"
implementation "com.example:bar:1.0"
}
Run Code Online (Sandbox Code Playgroud)
如果您在本地 Maven 存储库中安装生成的 jar 文件(借助maven-publish插件),您将看到生成的pom.xml文件如下所示:
<dependency>
<groupId>com.example</groupId>
<artifactId>foo</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)
注意:api已转换为compile范围和implementation- 为runtime范围。
这允许该库的使用者避免在其编译类路径中存在运行时依赖项。
Cam*_*lva 11
来自gradle 文档:
\n\n让\xe2\x80\x99s 看一下基于 JVM 的项目的一个非常简单的构建脚本。
\n\nplugins {\n id \'java-library\'\n}\n\nrepositories {\n mavenCentral()\n}\n\ndependencies {\n implementation \'org.hibernate:hibernate-core:3.6.7.Final\'\n api \'com.google.guava:guava:23.0\'\n testImplementation \'junit:junit:4.+\'\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n执行
\n\n编译项目的生产源所需的依赖项不属于项目公开的 API 的一部分。例如,该项目使用 Hibernate 来实现其内部持久层。
\n\n应用程序编程接口
\n\n编译项目的生产源所需的依赖项是项目公开的 API 的一部分。例如,该项目使用 Guava 并在其方法签名中公开带有 Guava 类的公共接口。
\n
想想你拥有app它采用模块lib1作为一个库和lib1使用lib2作为一个库。像这样的东西:app -> lib1 -> lib2。
现在,在中使用api lib2时lib1,然后在模块中使用:或时app 可以看到 lib2代码。api lib1implementation lib1app
但是使用的时候implementation lib2在lib1,则app 无法看到的lib2代码。
Answers from @matpag and @dev-bmax are clear enough to make people understand different usages between implementation and api. I just want to make an extra explaination from another angle, hopes to help for peoples that have the same question.
I created two projects for testing :
The dependencies hierarchy descripted above looks like:
[project-b] -> [project-a] -> [spring-boot-gradle-plugin]
Then I tested following scenarios:
Make project A depends on 'org.springframework.boot:spring-boot-gradle-plugin:1.5.20.RELEASE' by implementation .
Run gradle dependencies command in a terminal in poject B root dir?with following screenshot of output we can see that 'spring-boot-gradle-plugin' appears in runtimeClasspath dependencies tree, but not in compileClasspath's, I think that's exactly why we can't make use of library that declared using implementation, it just won't through compilation.
Make project A depends on 'org.springframework.boot:spring-boot-gradle-plugin:1.5.20.RELEASE' by api
Run gradle dependencies command in a terminal in poject B root dir again.
Now 'spring-boot-gradle-plugin' appears both in compileClasspath and runtimeClasspath dependencies tree.
A significant difference I noticed is that the dependency in producer/library project declared in implementation way won't appear in compileClasspath of consumer projects, so that we can't make use of corresponding lib in the consumer projects.
| 归档时间: |
|
| 查看次数: |
47885 次 |
| 最近记录: |