web-dev-qa-db-ja.com

Gradleでの実装とコンパイルの違いは何ですか?

Android Studio 3.0にアップデートして新しいプロジェクトを作成した後、build.gradleではcompileの代わりにimplementationの代わりにtestCompileの代わりにtestImplementationが新しい依存関係を追加する新しい方法があることに気付きました。

例:

 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'

それらの違いは何ですか?また何を使うべきですか?

745
humazed

tl; dr

ただ交換してください:

これはGradle 3.0に伴う重大な変更の1つです(GoogleはIO17 で発表しました)。

compileの設定は 現在は非推奨です で、implementationまたはapiに置き換えられます

Gradleドキュメント :から)

dependencies {
    api 'commons-httpclient:commons-httpclient:3.1'
    implementation 'org.Apache.commons:commons-lang3:3.5'
}

api設定に現れる依存関係は、ライブラリの消費者に推移的に公開され、そのため、消費者のコンパイルクラスパスに現れます。

一方、implementation設定にある依存関係は、コンシューマには公開されないため、コンシューマのコンパイルクラスパスにリークすることはありません。これにはいくつかの利点があります。

  • 依存関係がコンシューマのコンパイルクラスパスに漏れることはもうないので、誤って推移的な依存関係に依存することは決してありません。
  • クラスパスサイズの縮小によるコンパイルの高速化
  • 実装の依存関係が変わったときの再コンパイルの減少:コンシューマを再コンパイルする必要がない
  • クリーンなパブリッシング:新しいmaven-publishプラグインと組み合わせて使用​​すると、Javaライブラリは、ライブラリに対してコンパイルするために必要なものと実行時にライブラリを使用するために必要なものを正確に区別するPOMファイルを生成しますライブラリ自体をコンパイルするために必要なものとライブラリに対してコンパイルするために必要なものを混在させる)。

コンパイル設定はまだ存在しますが、apiimplementation設定が提供する保証を提供しないので使用しないでください。


注: アプリケーションモジュールでライブラリのみを使用している場合(一般的な場合)、違いはありません。
互いに依存するモジュールを含む複雑なプロジェクトがある場合、またはライブラリを作成している場合にのみ違いがわかります。

984
humazed

この答えは、プロジェクトのimplementationapi、およびcompileの違いを示します。


3つのGradleモジュールを含むプロジェクトがあるとしましょう。

  • アプリ(Androidアプリケーション)
  • myandroidlibrary(Androidライブラリ)
  • myjavalibrary(Javaライブラリ)

appは依存関係としてmyandroidlibraryを持っています。 myandroidlibraryは依存関係としてmyjavalibraryを持っています。

Dependency1

myjavalibraryMySecretクラスを持っています

public class MySecret {

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

myandroidlibraryMyAndroidComponentクラスの値を操作するMySecretクラスを持ちます。

public class MyAndroidComponent {

    private static String component = MySecret.getSecret();

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

最後に、appmyandroidlibraryからの値にのみ関心があります。

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

それでは、依存関係について話しましょう...

app:myandroidlibraryを消費する必要があるので、app build.gradleではimplementationを使用します。

:あなたもapi/compileを使うことができます。しかしその考えをちょっと待ってください。)

dependencies {
    implementation project(':myandroidlibrary')      
}

Dependency2

myandroidlibrary build.gradleはどのように見えるべきですか?どの範囲を使うべきですか?

3つの選択肢があります。

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

Dependency3

それらの違いは何ですか?また何を使うべきですか?

コンパイルまたはApi(オプション#2または#3) Dependency4

compileまたはapiを使用している場合私たちのAndroidアプリケーションはmyandroidcomponentクラスであるMySecret依存関係にアクセスできるようになりました。

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

実装(オプション#1)

Dependency5

implementation設定を使用している場合、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を使用してください。

依存関係を公開したくない場合は (内部モジュールを隠して)それからimplementationを使用してください。

注意:

これは単なるGradle構成の要点です。 表49.1を参照してください。 Javaライブラリプラグイン - 依存関係の宣言に使用される設定 より詳細な説明。

この回答のサンプルプロジェクトは https://github.com/aldoKelvianto/ImplementationVsCompile にあります。

241
aldok

Compile設定は推奨されなくなったので、implementationまたはapiに置き換えてください。

このドキュメントは https://docs.gradle.org/current/userguide/Java_library_plugin.html#sec:Java_library_separation にあります。

短い部分は

標準のJavaプラグインとJavaライブラリプラグインの主な違いは、後者が消費者に公開されるAPIの概念を導入することです。ライブラリは、他のコンポーネントによって消費されることを意図したJavaコンポーネントです。これはマルチプロジェクトビルドでは非常に一般的なユースケースですが、外部の依存関係があるとすぐにも起こります。

プラグインは、依存関係を宣言するために使用できる2つの設定を公開しています:apiとimplementationです。 API構成は、ライブラリAPIによってエクスポートされる依存関係を宣言するために使用する必要がありますが、実装構成は、コンポーネントの内部にある依存関係を宣言するために使用する必要があります。

詳しい説明については、この画像を参照してください。 Brief explanation

57
Rishav

簡単な解決策:

より良い方法は、すべての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'
         })
 }

さらに説明する:

Android Gradle plugin 3.0より前のバージョン: :1つのコードを変更するとすべてのモジュールが再コンパイルされるという大きな問題がありました。その根本的な原因は、Gradleが、モジュールのインターフェースを他のインターフェースを通してリークしているかどうかを知らないことです。

Android Gradleプラグイン3.0以降 :最新のAndroid Gradleプラグインでは、モジュールのインターフェースをリークするかどうかを明示的に定義する必要があります。それに基づいて、それは何を再コンパイルすべきかについて正しい選択をすることができます。

そのため、compile依存関係は非推奨となり、2つの新しい依存関係に置き換えられました。

  • api:あなたはあなた自身のインターフェースを通してこのモジュールのインターフェースをリークします。これは古いcompile依存関係と全く同じ意味です。

  • implementation:あなたはこのモジュールを内部的に使うだけで、あなたのインターフェースを通してそれをリークすることはありません

そのため、使用されているモジュールのインターフェースが変更されたかどうかにかかわらず、Gradleにモジュールを再コンパイルするように明示的に指示することができます。

提供: Jeroen Mols ブログ

42
Shayan Amani

素人の言葉の簡単な違いは、次のとおりです。

  • 上記の依存関係のメンバーを公開することによって他のモジュールへのサポートを提供するインターフェースまたはモジュールに取り組んでいる場合は、 'api'を使用する必要があります。
  • あなたが内部で述べられた依存関係を実装または使用しようとしているアプリケーションまたはモジュールを作っているならば、 'implementation'を使用してください。
  • 'compile'は 'api'と同じように機能しますが、あなたがライブラリを実装または使用しているだけの場合、 'implementation'はよりうまく機能しリソースを節約します。

包括的な例として@aldokの答えを読んでください。

6
Rushabh Agarwal
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| 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.  |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
5
Wajid Ali