在更新到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'

它们之间的区别是什么,我应该用什么?


当前回答

在继续之前先做一些笔记;compile已弃用,并且文档声明您应该使用implementation,因为compile将在Gradle 7.0版本中被删除。 如果你使用——warning-mode运行Gradle构建,你会看到以下消息:

对于依赖项声明,compile配置已弃用。这将失败,并在Gradle 7.0中出现错误。请改用实现配置。


只要看看帮助页上的图片,就很有意义了。

你有蓝色框compileClasspath和runtimeClassPath。 当运行gradle build时,compileClasspath是成功构建所必需的。编译时将出现在类路径上的库将是在gradle构建中使用compileOnly或implementation配置的所有库。

然后我们有runtimeClasspath,这些都是使用实现或runtimeOnly添加的包。所有这些库都将添加到您部署到服务器上的最终构建文件中。

如图所示,如果您希望一个库既用于编译,又希望将它添加到构建文件中,那么应该使用实现。

runtimeOnly的示例可以是数据库驱动程序。 compileOnly的一个例子可以是servlet-api。 实现的一个例子是spring-core。

其他回答

在继续之前先做一些笔记;compile已弃用,并且文档声明您应该使用implementation,因为compile将在Gradle 7.0版本中被删除。 如果你使用——warning-mode运行Gradle构建,你会看到以下消息:

对于依赖项声明,compile配置已弃用。这将失败,并在Gradle 7.0中出现错误。请改用实现配置。


只要看看帮助页上的图片,就很有意义了。

你有蓝色框compileClasspath和runtimeClassPath。 当运行gradle build时,compileClasspath是成功构建所必需的。编译时将出现在类路径上的库将是在gradle构建中使用compileOnly或implementation配置的所有库。

然后我们有runtimeClasspath,这些都是使用实现或runtimeOnly添加的包。所有这些库都将添加到您部署到服务器上的最终构建文件中。

如图所示,如果您希望一个库既用于编译,又希望将它添加到构建文件中,那么应该使用实现。

runtimeOnly的示例可以是数据库驱动程序。 compileOnly的一个例子可以是servlet-api。 实现的一个例子是spring-core。

+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| 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.  |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+

其他答案解释了这种差异。

只要确保对于Kotlin DSL (build.gradle.kts),函数应该有圆括号,它们的字符串参数应该用双引号括起来,而不是单引号:

Groovy (build.gradle) 实现“com.android.support: appcompat-v7:25.0.0” testImplementation“junit: junit: 4.12” 芬兰湾的科特林(build.gradle.kts) 实现(“com.android.support: appcompat-v7:25.0.0”) testImplementation(“junit: junit: 4.12”)

门外汉术语的简单区别是:

如果你正在处理一个接口或模块,它通过公开所声明的依赖关系的成员来为其他模块提供支持,你应该使用'api'。 如果你正在创建一个应用程序或模块,要在内部实现或使用声明的依赖项,请使用'implementation'。 'compile'与'api'工作方式相同,但是,如果你只是实现或使用任何库,'implementation'将更好地工作并节省资源。

阅读@aldok的回答以获得一个全面的示例。

这个答案将演示项目中的实现、api和编译之间的区别。


假设我有一个有三个Gradle模块的项目:

app (Android应用程序) myandroidlibrary(一个Android库) myjavalibrary(一个Java库)

应用程序有myandroidlibrary作为依赖项。Myandroidlibrary有myjavlibrary作为依赖项。

myjavlibrary有一个MySecret类

public class MySecret {

    public static String getSecret() {
        return "Money";
    }
}

myandroidlibrary中有MyAndroidComponent类,用于操作MySecret类的值。

public class MyAndroidComponent {

    private static String component = MySecret.getSecret();

    public static String getComponent() {
        return "My component: " + component;
    }    
}

最后,app只对myandroidlibrary的值感兴趣

TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());

现在,让我们谈谈依赖关系……

应用需要消耗:myandroidlibrary,所以在应用构建中。Gradle使用实现。

(注意:你也可以使用api/compile。但请稍等片刻。)

dependencies {
    implementation project(':myandroidlibrary')      
}

你认为myandroidlibrary构建了什么?Gradle应该是什么样子?我们应该使用哪个作用域?

我们有三个选择:

dependencies {
    // Option #1
    implementation project(':myjavalibrary') 
    // Option #2
    compile project(':myjavalibrary')      
    // Option #3
    api project(':myjavalibrary')           
}

它们之间的区别是什么,我应该用什么?

编译或Api(选项#2或#3)

如果你使用的是编译器或者api。我们的Android应用现在可以访问myandroidcomponent依赖,这是一个MySecret类。

TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());

实现(选项#1)

如果您正在使用实现配置,MySecret将不会公开。

TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile

那么,应该选择哪种配置呢?那要看你的要求了。

如果你想公开依赖关系,请使用api或compile。

如果你不想公开依赖关系(隐藏你的内部模块),那么使用实现。

注意:

这只是Gradle配置的一个要点,参见表49.1。Java库插件-用于声明依赖关系的配置,以获得更详细的解释。

这个答案的示例项目可以在https://github.com/aldoKelvianto/ImplementationVsCompile上找到