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?

561
demandé sur Peter Mortensen 2017-06-12 10:13:13

5 réponses

tl; dr

remplacer simplement:

  • compile avec implementation
  • testCompile avec testImplementation
  • debugCompile avec debugImplementation
  • androidTestCompile avec androidTestImplementation
  • 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 :

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

Les dépendances

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 et implementation 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.

766
répondu humazed 2018-08-21 21:18:43

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

138
répondu aldok 2018-06-18 08:34:09

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.

Pour plus d'explications, reportez-vous à cette image. Brief explanation

43
répondu Rishav 2017-06-12 07:37:04

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'ancienne compile 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

33
répondu SHi ON 2018-02-07 23:33:40

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.

1
répondu Rushabh Agarwal 2018-05-23 03:12:35