[android] Quelle est la différence entre l'implémentation et la compilation dans Gradle



Answers

Cette réponse va démontrer la différence entre l' implementation , l' api et la 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 tant que dépendances. myandroidlibrary a myjavalibrary comme dépendances.

application -> myandroidlibrary -> myjavalibrary

myjavalibrary a une classe MySecret

public class MySecret {

    public static String getSecret() {
        return "Money";
    }
}

myandroidlibrary a MyAndroidComponent classe MyAndroidComponent qui manipule la valeur de la classe MySecret .

public class MyAndroidComponent {

    private static String component = MySecret.getSecret();

    public static String getComponent() {
        return "My component: " + component;
    }    
}

Enfin, l' 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 l' app build.gradle. C'est très simple et intuitif.

dependencies {
    implementation project(':myandroidlibrary')      
}

À quoi pensez-vous que 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 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());

la mise en oeuvre

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

Ceci est juste un aperçu des configurations de Gradle, se référer au Tableau 49.1. Plugin Java Library - configurations utilisées pour déclarer les dépendances pour une explication plus détaillée.

Question

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 à la place 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?




Brève solution:

La meilleure approche consiste à remplacer toutes les dépendances de compile dépendances d' implementation . 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 Android Gradle plugin 3.0 : nous avons eu un gros problème qui est qu'un changement de code entraîne la recompilation de tous les modules. La cause première de ceci est que Gradle ne sait pas si vous fuyez l'interface d'un module par un autre ou non.

Après Android Gradle plugin 3.0 : le dernier plugin Android Gradle vous demande maintenant de définir explicitement si vous perdez l'interface d'un module. Basé sur cela, il peut faire le bon choix sur ce qu'il devrait recompiler.

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

  • api : vous perdez l'interface de ce module via votre propre interface, ce qui signifie exactement la même chose que l'ancienne dépendance de la compile

  • implementation : vous utilisez uniquement ce module en interne et ne le fuit pas via votre interface

Donc maintenant vous pouvez dire explicitement à Gradle de recompiler un module si l'interface d'un module utilisé change ou non.

Courtoisie du blog de Jeroen Mols




Links