Question 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 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?


510
2018-06-12 07:13


origine


Réponses:


C'est l'un des changements de rupture venant avec Gradle 3.0 que Google annoncé à IO17.

le compile la configuration est maintenant obsolète et devrait être remplacé par implementation ou api

Du Documentation de Gradle:

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

Dépendances apparaissant dans le api les configurations seront   exposés de manière transitoire aux consommateurs de la bibliothèque, et à ce titre   apparaissent sur le chemin de classe de compilation des consommateurs.

Dépendances trouvées dans le implementation configuration sera, 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 avantages:

  • les dépendances ne fuient plus dans le chemin de classe de compilation des consommateurs, donc vous ne dépendrez jamais accidentellement d'un transitif   dépendance
  • compilation plus rapide grâce à la réduction de la taille du chemin de classe
  • moins de recompilations lorsque les dépendances d'implémentation changent: les utilisateurs n'auraient pas besoin d'être recompilés
  • publication plus propre: lorsqu'ils sont utilisés conjointement avec le nouveau plugin maven-publish, les bibliothèques Java produisent des fichiers POM   distinguer exactement entre ce qui est nécessaire pour compiler contre le   bibliothèque et ce qui est requis pour utiliser la bibliothèque à l'exécution (dans d'autres   mots, ne pas mélanger ce qui est nécessaire pour compiler la bibliothèque elle-même et   est nécessaire pour compiler contre la bibliothèque).

La configuration de compilation existe toujours, mais ne doit pas être utilisée car elle n'offrira pas les garanties que le api et implementation configurations fournissent.


tl; dr

Remplace juste:

  • compile avec implementation
  • testCompile avec testImplementation
  • debugCompile avec debugImplementation
  • androidTestCompile avec androidTestImplementation
  • compileOnly est toujours valide. Il a été ajouté en 3.0 pour remplacer fourni et non compilé. (provided introduit lorsque Gradle n'avait pas de nom de configuration pour ce cas d'utilisation et le nommait après l'étendue fournie par Maven.)

689
2018-06-12 07:13



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:

  • application (une application Android)
  • myandroidlibrary (une bibliothèque Android)
  • myjavalibrary (une bibliothèque Java)

app a myandroidlibrary en tant que dépendances. myandroidlibrary a myjavalibrary  comme dépendances.

application -> myandroidlibrary -> myjavalibrary

myjavalibrary a un 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 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 sur app build.gradle. C'est très simple et intuitif.

dependencies {
    implementation project(':myandroidlibrary')      
}

Qu'est-ce que tu penses myandroidlibrary build.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 utilisez compile et api. Notre application Android maintenant en mesure d'accéder myandroidcomponentdépendance, qui est un MySecret classe.

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

la mise en oeuvre

Si vous utilisez implementation configuration, 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 voulez exposer les dépendances, utilisez api ou compile, si vous ne voulez pas exposer les dépendances (en cachant votre module interne), utilisez implementation.

Ceci est juste un résumé des configurations de Gradle, se référer à Tableau 49.1. Plugin Java 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


114
2018-01-22 18:55



Compile la configuration était obsolète et devrait être remplacée par implementation ou api.

Vous pouvez lire les documents à https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation.

La partie brève étant ...

La différence clé entre le plugin Java standard et le Java   Le plugin Library est que ce dernier introduit le concept d'API   exposés aux consommateurs. Une bibliothèque est un composant Java destiné à être   consommé par d'autres composants. C'est un cas d'utilisation très commun dans   multi-projets, mais aussi dès que vous avez externe   dépendances.

Le plugin expose deux configurations qui peuvent être utilisées pour déclarer   dépendances: api et implémentation. La configuration de l'api devrait être   utilisé pour déclarer les dépendances exportées par l'API de bibliothèque,   alors que la configuration d'implémentation doit être utilisée pour déclarer   les dépendances internes au composant.

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


43
2018-06-12 07:37



Brève solution:

La meilleure approche consiste à remplacer tous compile dépendances avec implementation dépendances. Et seulement lorsque vous fuyez 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'
         })
 }

Explique plus:

Avant le plugin Android Gradle 3.0: nous avons eu un gros problème: un changement de code entraîne la recompilation de tous les modules. La cause principale de ceci est que Gradle ne sait pas si l’interface d’un module passe par l’autre ou non.

Après le plugin Android Gradle 3.0: le dernier plug-in Android Gradle vous demande maintenant de définir explicitement si vous perdez l'interface d'un module. Sur cette base, il peut faire le bon choix sur ce qu’il doit recompiler.

En tant que tel compile la dépendance a été dépréciée et remplacée par deux nouvelles:

  • api: vous fuyez l'interface de ce module à travers votre propre interface, ce qui signifie exactement la même chose que l'ancien compile dépendance

  • implementation: vous n'utilisez ce module qu'en interne et ne le fuyez pas via votre interface

Alors maintenant, vous pouvez explicitement demander à Gradle de recompiler un module si l’interface d’un module utilisé change ou non.

Courtoisie de Jeroen Mols Blog


29
2018-01-07 21:16



La brève différence dans le terme de profane est la suivante:

  • Si vous travaillez sur une interface ou un module qui prend en charge 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 indiquée en interne, utilisez 'implementation'.
  • 'compile' a fonctionné de la même manière que 'api', cependant, si vous ne faites que l'implémentation ou l'utilisation d'une bibliothèque, 'implementation' fonctionnera mieux et vous fera économiser des ressources.

lisez la réponse de @aldok pour un exemple complet.


1
2018-05-23 03:12