Androidのメーカー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'
それらの違いは何ですか?私は何を使うべきですか?
tl; dr
交換するだけです:
compile
implementation
(あなたが推移性を必要としない場合)、またはapi
(あなたが推移性を必要とする場合)testCompile
と testImplementation
debugCompile
と debugImplementation
androidTestCompile
と androidTestImplementation
compileOnly
まだ有効です。コンパイルではなく提供されたものを置き換えるために3.0で追加されました。(provided
Gradleにそのユースケースの構成名がなく、Mavenが提供するスコープにちなんで名前を付けたときに導入されました。)これは、GoogleがIO17で発表したAndroidGradleプラグイン3.0に伴う重大な変更の1つです。
compile
設定がされて廃止とで交換する必要がありますimplementation
かapi
dependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.apache.commons:commons-lang3:3.5' }
api
構成に表示される依存関係は、ライブラリのコンシューマーに推移的に公開されるため、コンシューマーのコンパイルクラスパスに表示されます。
implementation
一方、構成で見つかった依存関係はコンシューマーに公開されないため、コンシューマーのコンパイルクラスパスにリークすることはありません。これにはいくつかの利点があります。
- 依存関係がコンシューマーのコンパイルクラスパスにリークすることがなくなったため、推移的な依存関係に誤って依存することはありません。
- クラスパスサイズの縮小によるコンパイルの高速化
- 実装の依存関係が変更された場合の再コンパイルが少なくなる:コンシューマーを再コンパイルする必要がない
- よりクリーンな公開:新しいmaven-publishプラグインと組み合わせて使用すると、Javaライブラリは、ライブラリに対してコンパイルするために必要なものと、実行時にライブラリを使用するために必要なものを正確に区別するPOMファイルを生成します(つまり、しないでください)。ライブラリ自体をコンパイルするために必要なものと、ライブラリに対してコンパイルするために必要なものを混合します)。
コンパイル構成はまだ存在
api
しimplementation
ますが、および構成が提供する保証を提供しないため、使用しないでください。
注:アプリモジュールでライブラリのみを使用している場合(一般的なケース)、違いに気付くことはありません。
モジュールが相互に依存している複雑なプロジェクトがある場合、またはライブラリを作成している場合にのみ、違いがわかります。
この答えは、違いを実証するimplementation
、api
とcompile
のプロジェクトに。
3つのGradleモジュールを含むプロジェクトがあるとしましょう。
app
持っているmyandroidlibrary
依存関係として。myandroidlibrary
持っているmyjavalibrary
依存関係として。
myjavalibrary
持っている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());
それでは、依存関係について話しましょう...
app
消費する必要がある:myandroidlibrary
ため、app
build.gradleではを使用しますimplementation
。
(Note: You can use api/compile too. But hold that thought for a moment.)
dependencies {
implementation project(':myandroidlibrary')
}
What do you think myandroidlibrary
build.gradle should look like? Which scope we should use?
We have three options:
dependencies {
// Option #1
implementation project(':myjavalibrary')
// Option #2
compile project(':myjavalibrary')
// Option #3
api project(':myjavalibrary')
}
What's the difference between them and what should I be using?
Compile or Api (option #2 or #3)
If you're using compile
or api
. Our Android Application now able to access myandroidcomponent
dependency, which is a MySecret
class.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());
Implementation (option #1)
If you're using implementation
configuration, MySecret
is not exposed.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile
So, which configuration you should choose? That really depends on your requirement.
If you want to expose dependencies use api
or compile
.
If you don't want to expose dependencies (hiding your internal module) then use implementation
.
Note:
This is just a gist of Gradle configurations, refer to Table 49.1. Java Library plugin - configurations used to declare dependencies for more detailed explanation.
The sample project for this answer is available on https://github.com/aldoKelvianto/ImplementationVsCompile
Compile
configuration was deprecated and should be replaced by implementation
or api
.
You can read the docs at https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation.
The brief part being-
The key difference between the standard Java plugin and the Java Library plugin is that the latter introduces the concept of an API exposed to consumers. A library is a Java component meant to be consumed by other components. It's a very common use case in multi-project builds, but also as soon as you have external dependencies.
The plugin exposes two configurations that can be used to declare dependencies: api and implementation. The api configuration should be used to declare dependencies which are exported by the library API, whereas the implementation configuration should be used to declare dependencies which are internal to the component.
For further explanation refer to this image.
Brief Solution:
The better approach is to replace all compile
dependencies with implementation
dependencies. And only where you leak a module’s interface, you should use api
. That should cause a lot less recompilation.
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'
})
}
Explain More:
Before Android Gradle plugin 3.0: we had a big problem which is one code change causes all modules to be recompiled. The root cause for this is that Gradle doesn’t know if you leak the interface of a module through another one or not.
After Android Gradle plugin 3.0: the latest Android Gradle plugin now requires you to explicitly define if you leak a module’s interface. Based on that it can make the right choice on what it should recompile.
As such the compile
dependency has been deprecated and replaced by two new ones:
api
: you leak the interface of this module through your own interface, meaning exactly the same as the old compile
dependency
implementation
: you only use this module internally and does not leak it through your interface
So now you can explicitly tell Gradle to recompile a module if the interface of a used module changes or not.
Courtesy of Jeroen Mols blog
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| 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. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
Gradle 3.0
introduced next changes:
compile
-> api
api
keyword is the same as deprecated compile
compile
-> implementation
Is preferable way because has some advantages. implementation
expose dependency only for one level up at build time (the dependency is available at runtime). As a result you have a faster build(no need to recompile consumers which are higher then 1 level up)
provided
-> compileOnly
This dependency is available only in compile time(the dependency is not available at runtime). This dependency can not be transitive and be .aar
. It can be used with compile time annotation processor and allows you to reduce a final output file
compile
-> annotationProcessor
Very similar to compileOnly
but also guarantees that transitive dependency are not visible for consumer
apk
-> runtimeOnly
Dependency is not available in compile time but available at runtime.
The brief difference in layman's term is:
read the answer by @aldok for a comprehensive example.
Since version 5.6.3 Gradle documentation provides simple rules of thumb to identify whether an old compile
dependency (or a new one) should be replaced with an implementation
or an api
dependency:
- Prefer the
implementation
configuration overapi
when possibleThis keeps the dependencies off of the consumer’s compilation classpath. In addition, the consumers will immediately fail to compile if any implementation types accidentally leak into the public API.
So when should you use the
api
configuration? An API dependency is one that contains at least one type that is exposed in the library binary interface, often referred to as its ABI (Application Binary Interface). This includes, but is not limited to:
- types used in super classes or interfaces
- types used in public method parameters, including generic parameter types (where public is something that is visible to compilers. I.e. , public, protected and package private members in the Java world)
- types used in public fields
- public annotation types
By contrast, any type that is used in the following list is irrelevant to the ABI, and therefore should be declared as an
implementation
dependency:
- types exclusively used in method bodies
- types exclusively used in private members
- types exclusively found in internal classes (future versions of Gradle will let you declare which packages belong to the public API)
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).
I have created a post with an in-depth understanding of each one with Working Example: source code
https://medium.com/@gauraw.negi/how-gradle-dependency-configurations-work-underhood-e934906752e5
特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。
ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。
ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。
あなたが一時的に会っていなかったとき。シーズン11-1を開始したチームであるニューヨークメッツは、日曜日の午後にフィラデルフィアで行われた最後の11試合の9試合目を失いました。
スティーブン・キングのアウトサイダーは、多くの点で先祖返りの小説であり、80年代の全盛期から引き裂かれたように見える生き物の特徴であり、おそらくセル以来の彼の最もパルプのような本ですが、今日の恐怖の中で間違いなく設立された作品です。表面上は、形を変えるペニーワイズのような子供たちの殺人者を中心としており、その最も暗い脅威は、封じ込められず、神経質に平凡なものよりも幻想的で打ち負かされません。
スティーブンユニバースビーチシティのエピソードが実行されるたびに、いくつかのクライマックスイベントが発生し、スティーブンユニバースのより広い神話に対する理解の一部が失われます。これはあなたが期待していたことですか?今日のエピソードは両方とも、容赦なくゆっくりと、シーズンの終盤の主要な部分を設定する決定的な結論に向かって進みます。そして、ロナウドは、静かな納屋が倒れているのを発見した夜中にスティーブンを捕まえるためにやって来ます。月に。
Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday
シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。
オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。
Vorresti diventare web developer e non sai da dove cominciare?! Qui troverai tutte le risposte necessarie, anche io non sapevo che strada intraprendere ma voglio aiutarti a non commettere i miei stessi errori. Cosa imparare? Le competenza essenziali per qualsiasi web developer sono almeno tre.
Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。
遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。
2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。