Gradle 实现与 API 配置 [英] Gradle Implementation vs API configuration
问题描述
我正在尝试在构建我的依赖项时找出 api
和 implementation
配置之间的区别.
在文档中,它说 implementation
有更好的构建时间,但是,看到这个评论 在一个类似的问题中,我想知道这是不是真的.
由于我不是 Gradle 的专家,我希望有人可以提供帮助.我已经阅读了文档,但我想知道一个易于-理解解释.
Gradle compile
关键字被弃用,取而代之的是 api
和 implementation
配置依赖项的关键字.
使用api
相当于使用不推荐使用的compile
,所以如果你用api
替换所有的compile
一切都会照常进行.
要理解 implementation
关键字,请考虑以下示例.
示例
假设您有一个名为 MyLibrary
的库,它在内部使用另一个名为 InternalLibrary
的库.像这样:
//'InternalLibrary' 模块公共类内部图书馆{公共静态字符串 giveMeAString(){返回你好";}}
//'MyLibrary' 模块公共类 MyLibrary {公共字符串 myString(){返回 InternalLibrary.giveMeAString();}}
假设 MyLibrary
build.gradle
在 dependencies{}
中使用 api
配置,如下所示:
依赖项{api 项目(':InternalLibrary')}
您想在代码中使用 MyLibrary
,因此在应用程序的 build.gradle
中添加此依赖项:
依赖项{实施项目(':MyLibrary')}
使用 api
配置(或已弃用的 compile
),您可以在应用程序代码中访问 InternalLibrary
:
//访问MyLibrary"(授予)MyLibrary myLib = new MyLibrary();System.out.println(myLib.myString());//也可以访问内部库(但你不应该)System.out.println(InternalLibrary.giveMeAString());
通过这种方式,MyLibrary
模块可能会泄漏"某事的内部实现.您不应该(能够)使用它,因为它不是由您直接导入的.
引入了 implementation
配置来防止这种情况.所以现在如果你在 MyLibrary
中使用 implementation
而不是 api
:
依赖项{实施项目(':InternalLibrary')}
您将无法再在应用代码中调用 InternalLibrary.giveMeAString()
.
这种装箱策略让Android Gradle插件知道如果你在InternalLibrary
中编辑了一些东西,它必须只触发MyLibrary
的重新编译,不会 重新编译整个应用程序,因为您无权访问 InternalLibrary
.
当您有很多嵌套依赖项时,此机制可以大大加快构建速度.(观看最后链接的视频以全面了解这一点)
结论
当您切换到新的 Android Gradle 插件 3.XX 时,您应该将所有
compile
替换为implementation
关键字 *(1)<强>.然后尝试编译和测试您的应用程序.如果一切正常,就让代码保持原样,如果您遇到问题,您的依赖项可能有问题,或者您使用了现在私有且无法访问的东西.*Android Gradle 插件工程师 Jerome Dochez 的建议 (1))如果您是库管理员,您应该对库的公共 API 所需的每个依赖项使用
api
,而对测试依赖项使用implementation
或最终用户不得使用的依赖项.
实用文章实现和api
参考资料(这是为了节省时间而拆分的同一视频)
Google I/O 2017 - 如何加速 Gradle 构建(完整视频)
Google I/O 2017 - 如何加速 Gradle 构建(仅限新 GRADLE 插件 3.0.0 部分))
Google I/O 2017 - 如何加速 Gradle 构建(参考 1强>*)
I'm trying to figure out what is the difference between api
and implementation
configuration while building my dependencies.
In the documentation, it says that implementation
has better build time, but,
seeing this comment in a similar question I got to wonder if is it true.
Since I'm no expert in Gradle, I hope someone can help. I've read the documentation already but I was wondering about an easy-to-understand explanation.
Gradle compile
keyword was deprecated in favor of the api
and implementation
keywords to configure dependencies.
Using api
is the equivalent of using the deprecated compile
, so if you replace all compile
with api
everything will works as always.
To understand the implementation
keyword consider the following example.
EXAMPLE
Suppose you have a library called MyLibrary
that internally uses another library called InternalLibrary
. Something like this:
// 'InternalLibrary' module
public class InternalLibrary {
public static String giveMeAString(){
return "hello";
}
}
// 'MyLibrary' module
public class MyLibrary {
public String myString(){
return InternalLibrary.giveMeAString();
}
}
Suppose the MyLibrary
build.gradle
uses api
configuration in dependencies{}
like this:
dependencies {
api project(':InternalLibrary')
}
You want to use MyLibrary
in your code so in your app's build.gradle
you add this dependency:
dependencies {
implementation project(':MyLibrary')
}
Using the api
configuration (or deprecated compile
) you can access InternalLibrary
in your application code:
// Access 'MyLibrary' (granted)
MyLibrary myLib = new MyLibrary();
System.out.println(myLib.myString());
// Can ALSO access the internal library too (but you shouldn't)
System.out.println(InternalLibrary.giveMeAString());
In this way the module MyLibrary
is potentially "leaking" the internal implementation of something. You shouldn't (be able to) use that because it's not directly imported by you.
The implementation
configuration was introduced to prevent this.
So now if you use implementation
instead of api
in MyLibrary
:
dependencies {
implementation project(':InternalLibrary')
}
you won't be able to call InternalLibrary.giveMeAString()
in your app code anymore.
This sort of boxing strategy allows Android Gradle plugin to know that if you edit something in InternalLibrary
, it must only trigger the recompilation of MyLibrary
and not the recompilation of your entire app, because you don't have access to InternalLibrary
.
When you have a lot of nested dependencies this mechanism can speed up the build a lot. (Watch the video linked at the end for a full understanding of this)
CONCLUSIONS
When you switch to the new Android Gradle plugin 3.X.X, you should replace all your
compile
with theimplementation
keyword *(1). Then try to compile and test your app. If everything it's ok leave the code as is, if you have problems you probably have something wrong with your dependencies or you used something that now is private and not more accessible. *Suggestion by Android Gradle plugin engineer Jerome Dochez (1))If you are a library mantainer you should use
api
for every dependency which is needed for the public API of your library, while useimplementation
for test dependencies or dependencies which must not be used by the final users.
Useful article Showcasing the difference between implementation and api
REFERENCES (This is the same video splitted up for time saving)
Google I/O 2017 - How speed up Gradle builds (FULL VIDEO)
Google I/O 2017 - How speed up Gradle builds (NEW GRADLE PLUGIN 3.0.0 PART ONLY)
Google I/O 2017 - How speed up Gradle builds (reference to 1*)
这篇关于Gradle 实现与 API 配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!