Après la mise à jour vers Android Studio 3.0 et la création d'un nouveau projet, j'ai remarqué que, dans build.gradle
, il existe un nouveau moyen d'ajouter de nouvelles dépendances au lieu de compile
, il y a implementation
. et au lieu de testCompile
, il y a testImplementation
.
Exemple:
implementation 'com.Android.support:appcompat-v7:25.0.0'
testImplementation 'junit:junit:4.12'
au lieu de
compile 'com.Android.support:appcompat-v7:25.0.0'
testCompile 'junit:junit:4.12'
Quelle est la différence entre eux et que devrais-je utiliser?
tl; dr
Il suffit de remplacer:
compile
avec implementation
(si vous n'avez pas besoin de transitivité) ou api
(si vous avez besoin de transitivité)testCompile
avec testImplementation
debugCompile
avec debugImplementation
androidTestCompile
avec androidTestImplementation
compileOnly
est toujours valide. Il a été ajouté dans la version 3.0 pour remplacer fourni et non compilé. (provided
introduit lorsque Gradle ne possède pas de nom de configuration pour ce cas d'utilisation et le nomme d'après l'étendue fournie par Maven.)C'est l'un des changements marquants à venir avec Gradle 3.0 que Google annoncé à IO17 .
La configuration de compile
est maintenant obsolète et doit être remplacée par implementation
ou api
De la documentation Gradle :
dependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.Apache.commons:commons-lang3:3.5' }
Les dépendances apparaissant dans les configurations
api
seront exposées de manière transitoire aux utilisateurs de la bibliothèque et, en tant que telles, apparaîtront sur le chemin de classe de compilation des utilisateurs.En revanche, les dépendances trouvées dans la configuration
implementation
ne seront pas exposées aux consommateurs et ne s'infiltreront donc pas dans le chemin de classe de compilation de ces derniers. Cela comporte plusieurs avantages:
- les dépendances ne fuient plus dans le chemin de classe de compilation des consommateurs, vous ne dépendez donc jamais accidentellement d'une dépendance transitive
- compilation plus rapide grâce à la réduction de la taille des chemins de classes
- moins de recompilations lorsque les dépendances de mise en œuvre changent: les consommateurs n'auraient pas besoin d'être recompilés
- édition plus propre: lorsqu'elles sont utilisées avec le nouveau plugin maven-publish, les bibliothèques Java produisent des fichiers POM qui font la distinction entre ce qui est nécessaire pour compiler avec la bibliothèque et ce qui est requis pour utiliser la bibliothèque à l'exécution En d'autres termes, ne mélangez pas ce qui est nécessaire pour compiler la bibliothèque elle-même et ce qui est nécessaire pour compiler avec la bibliothèque).
La configuration de compilation existe toujours, mais ne doit pas être utilisée car elle n'offrira pas les garanties fournies par les configurations
api
etimplementation
.
Remarque: Si vous utilisez uniquement une bibliothèque dans votre module d'application (dans le cas habituel), vous ne remarquerez aucune différence.
vous ne verrez la différence que si vous avez un projet complexe avec des modules qui dépendent les uns des autres ou si vous créez une bibliothèque.
Cette réponse démontrera la différence entre implementation
, api
et compile
sur un projet.
Disons que j'ai un projet avec trois modules Gradle:
app
a myandroidlibrary
comme dépendances. myandroidlibrary
a myjavalibrary
comme dépendances.
myjavalibrary
a une classe MySecret
public class MySecret {
public static String getSecret() {
return "Money";
}
}
myandroidlibrary
a MyAndroidComponent
classe qui manipule la valeur de MySecret
classe.
public class MyAndroidComponent {
private static String component = MySecret.getSecret();
public static String getComponent() {
return "My component: " + component;
}
}
Enfin, app
ne s'intéresse qu'à la valeur de myandroidlibrary
TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());
Parlons maintenant des dépendances ...
app
doit consommer :myandroidlibrary
, donc dans app
build.gradle, utilisez implementation
.
( Note : Vous pouvez aussi utiliser api/compile. Mais gardez cette pensée un instant.)
dependencies {
implementation project(':myandroidlibrary')
}
À quoi pensez-vous que myandroidlibrary
build.gradle devrait ressembler? Quelle portée devrions-nous utiliser?
Nous avons trois options:
dependencies {
// Option #1
implementation project(':myjavalibrary')
// Option #2
compile project(':myjavalibrary')
// Option #3
api project(':myjavalibrary')
}
Quelle est la différence entre eux et que devrais-je utiliser?
Compiler ou Api (option n ° 2 ou n ° 3)
Si vous utilisez compile
ou api
. Notre application Android peut maintenant accéder à la dépendance myandroidcomponent
, qui est une classe MySecret
.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());
Mise en oeuvre (option n ° 1)
Si vous utilisez la configuration implementation
, MySecret
n'est pas exposé.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile
Alors, quelle configuration choisir? Cela dépend vraiment de vos besoins.
Si vous souhaitez exposer des dépendances , utilisez api
ou compile
.
Si vous ne souhaitez pas exposer les dépendances (masquer votre module interne), utilisez implementation
.
Remarque:
Ceci est juste un résumé des configurations de Gradle, voir Tableau 49.1. Java plug-in Library - configurations utilisées pour déclarer des dépendances pour une explication plus détaillée.
L'exemple de projet pour cette réponse est disponible sur https://github.com/aldoKelvianto/ImplementationVsCompile
La configuration de Compile
est obsolète et doit être remplacée par implementation
ou api
.
Vous pouvez lire la documentation sur https://docs.gradle.org/current/userguide/Java_library_plugin.html#sec:Java_library_separation .
La brève partie étant-
La principale différence entre le plug-in standard Java et le plug-in Java Library est que ce dernier introduit le concept d'une API exposée aux consommateurs. Une bibliothèque est un composant Java destiné à être utilisé par d'autres composants. C'est un cas d'utilisation très courant dans les versions multi-projets, mais aussi dès que vous avez des dépendances externes.
Le plugin expose deux configurations pouvant être utilisées pour déclarer des dépendances: api et implémentation. La configuration de l'api doit être utilisée pour déclarer les dépendances exportées par l'API de la bibliothèque, tandis que la configuration de l'implémentation doit être utilisée pour déclarer les dépendances internes au composant.
Brève solution:
La meilleure approche consiste à remplacer toutes les dépendances compile
par des dépendances implementation
. Et uniquement lorsque l'interface d'un module présente une fuite, vous devez utiliser api
. Cela devrait causer beaucoup moins de 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'
})
}
Expliquez plus:
Avant Android Gradle plugin 3.0 : nous avons eu un gros problème, à savoir qu'un changement de code entraîne la recompilation de tous les modules. La cause fondamentale de ceci est que Gradle ne sait pas si vous divulguez l’interface d’un module par un autre ou non.
Après Android Gradle plug-in 3.0 : le dernier plug-in Android Gradle nécessite désormais que vous définissiez explicitement votre fuite. une interface de module. Basé sur cela, il peut faire le bon choix sur ce qu'il devrait recompiler.
En tant que telle, la dépendance compile
est devenue obsolète et remplacée par deux nouvelles:
api
: l'interface de ce module fuit via sa propre interface, ce qui signifie exactement la même chose que l'ancienne dépendance compile
implementation
: vous utilisez ce module uniquement en interne et ne le perdez pas via votre interface
Vous pouvez donc maintenant explicitement demander à Gradle de recompiler un module si l’interface d’un module utilisé change ou non.
Gracieuseté de Jeroen Mols blog
La brève différence dans le terme profane est:
lisez la réponse de @aldok pour un exemple complet.
+--------------------+----------------------+-------------+--------------+-----------------------------------------+
| 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. |
+--------------------+----------------------+-------------+--------------+-----------------------------------------+