Quelle est la différence entre l'implémentation et la compilation dans Gradle?
après la mise à jour vers Android Studio 3.0 et la création d'un nouveau projet, j'ai remarqué que dans gradle/" class="blnk">build.gradle
il y a une nouvelle façon 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?
5 réponses
tl; dr
remplacer simplement:
-
compile
avecimplementation
-
testCompile
avectestImplementation
-
debugCompile
avecdebugImplementation
-
androidTestCompile
avecandroidTestImplementation
-
compileOnly
est toujours valable. Il a été ajouté dans 3.0 Pour remplacer fourni et non compiler. (provided
introduit lorsque Gradle n'avait pas de nom de configuration pour ce user-case et l'a nommé d'après le scope fourni par Maven.)
C'est l'un des changements de rupture avec Gradle 3.0 que Google a annoncé à IO17 .
la configuration compile
est maintenant dépréciée et doit être remplacée par implementation
ou api
De la Gradle documentation :
Les dépendancesdependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.apache.commons:commons-lang3:3.5' }
apparaissant dans les configurations
Les dépendancesapi
seront transitivement exposés aux consommateurs de la bibliothèque, et en tant que tel ne apparaissent sur la compilation de chemin de classe de consommateurs.trouvées dans la configuration
implementation
seront, sur la d'autre part, ne pas être exposé aux consommateurs, et donc pas de fuite dans les consommateurs compilent classpath. Cela vient avec plusieurs prestations:
- les dépendances ne fuient plus dans la classe de compilation des consommateurs, donc vous ne dépendrez jamais accidentellement d'une transition dépendance
- compilation plus rapide grâce à la taille réduite de classpath
- moins de recompilations lorsque les dépendances de mise en œuvre changent: les consommateurs n'auraient pas besoin d'être recompilées
- nettoyeur de publication: lorsqu'il est utilisé en conjonction avec le nouveau plugin maven-publish, les bibliothèques Java produisent des fichiers POM qui distinguer exactement ce qui est requis pour compiler par rapport à bibliothèque et ce qui est nécessaire pour utiliser la bibliothèque à l'exécution (dans d'autres les mots, ne pas mélanger ce qui est nécessaire pour compiler la bibliothèque elle-même et ce qu' est nécessaire pour compiler la bibliothèque).
Les configurations
api
etimplementation
sont disponibles.
Note: si vous utilisez seulement une bibliothèque dans votre module app-le cas commun - vous ne remarquerez aucune différence.
vous ne verrez la différence, si vous avez un projet complexe avec des modules en fonction 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 (une application Android)
- myandroidlibrary (Android bibliothèque)
- myjavalibrary (une bibliothèque Java)
app
a myandroidlibrary
comme dépendances. myandroidlibrary
a myjavalibrary
comme dépendances.
app - > myandroidlibrary - > myjavalibrary
myjavalibrary
a une MySecret
classe
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 concerne que la valeur de myandroidlibrary
TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());
maintenant, parlons des dépendances sur app
construire.gradle. C'est très simple et intuitive.
dependencies {
implementation project(':myandroidlibrary')
}
Que pensez-vous de "1519110920 de construire".gradle devrait ressembler? 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 et Api
si vous êtes en utilisant compile
et api
. Notre application Android est maintenant capable d'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 Œuvre
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 pour exposer les dépendances, utilisez api
ou compile
, si vous ne voulez pas exposer les dépendances (cacher votre module interne), utilisez implementation
.
il s'agit d'une simple liste de configurations de grades, voir tableau 49.1. Java Library plugin-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
Compile
la configuration a été dépréciée et devrait être remplacée par implementation
ou api
.
vous pouvez lire le docs à https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation .
La brève partie-
la différence clé entre le plugin Java standard et le Java Bibliothèque plugin est que ce dernier introduit le concept D'une API exposés aux consommateurs. Une bibliothèque est un composant Java destiné à être consommées par d'autres composants. Il est d'un usage très courant en cas construction multi-projets, mais aussi dès que vous avez dépendance.
le plugin expose deux configurations qui peuvent être utilisées pour déclarer dépendances: api et implémentation. L'api de configuration doit être utilisé pour déclarer les dépendances qui sont exportées par L'API de bibliothèque, alors que la mise en œuvre la configuration doit être utilisée pour déclarer des dépendances internes au composant.
Brève Solution:
la meilleure approche consiste à remplacer toutes les dépendances compile
par des dépendances implementation
. Et seulement lorsque vous avez une fuite de l'interface d'un module, 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'
})
}
Expliquer Plus:
Avant Android Gradle plugin 3.0 : nous avons eu un gros problème qui est qu'un changement de code provoque la recompilation de tous les modules. La cause fondamentale de cela est que Gradle ne sait pas si vous fuyez l'interface d'un module à travers un autre ou pas.
D'après le plugin Android Gradle 3.0 : le dernier plugin Android Gradle vous demande maintenant de définir explicitement si vous avez une fuite de l'interface d'un module. Basé sur qui il peut faire le bon choix sur ce qu'il doit recompiler.
en tant que telle la dépendance compile
a été dépréciée et remplacée par deux nouvelles:
-
api
: vous filtrez l'interface de ce module à travers votre propre interface, ce qui signifie exactement la même chose que l'anciennecompile
dépendance -
implementation
: vous n'utilisez ce module qu'en interne et il ne fuit pas à travers votre interface
donc maintenant vous pouvez dire explicitement à 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 de layman est:
- si vous travaillez sur une interface ou un module qui fournit un support à d'autres modules en exposant les membres de la dépendance indiquée, vous devez utiliser 'api'.
- si vous créez une application ou un module qui va implémenter ou utiliser la dépendance mentionnée en interne, utilisez 'implémentation'.
- 'compiler' fonctionne comme 'api', cependant, si vous ne mettez en œuvre ou utilisez qu'une bibliothèque, 'implémentation' fonctionnera mieux et vous économiserez des ressources.
lire la réponse de @aldok pour un exemple complet.