Ich versuche herauszufinden, was der Unterschied zwischen api
und implementation
Konfiguration ist, während ich meine Abhängigkeiten aufbaue.
In der Dokumentation heißt es, dass implementation
die Bauzeit besser ist, aber als ich diesen Kommentar in einer ähnlichen Frage sah, musste ich mich fragen, ob er wahr ist.
Da ich kein Gradle-Experte bin, hoffe ich, dass jemand helfen kann. Ich habe die Dokumentation bereits gelesen , habe mich aber über eine leicht verständliche Erklärung gewundert.
android
gradle
dependencies
implementation
reinaldomoreira
quelle
quelle
compile
nach wechselnapi
. Die Bibliotheken, die Sie intern verwenden, können einige private Implementierungen verwenden, die in der endgültigen Bibliothek nicht verfügbar sind, sodass sie für Sie transparent sind. Diese "intern-privaten" Abhängigkeiten können umgeschaltet werden.implementation
Wenn das Android Gradle-Plugin Ihre App kompiliert, wird die Kompilierung dieser Abhängigkeiten übersprungen, was zu einer kürzeren Erstellungszeit führt (diese Abhängigkeiten sind jedoch zur Laufzeit verfügbar).Antworten:
Das Gradle-
compile
Schlüsselwort wurde zugunsten der Schlüsselwörterapi
und veraltetimplementation
, um Abhängigkeiten zu konfigurieren.Die Verwendung
api
entspricht der Verwendung der veraltetencompile
. Wenn Sie also allecompile
durchapi
alles ersetzen , funktioniert dies wie immer.Um das
implementation
Schlüsselwort zu verstehen, betrachten Sie das folgende Beispiel.BEISPIEL
Angenommen, Sie haben eine Bibliothek mit dem Namen
MyLibrary
, die intern eine andere Bibliothek mit dem Namen verwendetInternalLibrary
. Etwas wie das:Angenommen, die
MyLibrary
build.gradle
Verwendungskonfigurationapi
sieht folgendermaßen ausdependencies{}
:Sie möchten
MyLibrary
in Ihrem Code verwenden, alsobuild.gradle
fügen Sie in Ihren Apps diese Abhängigkeit hinzu:Mit der
api
Konfiguration (oder veraltetcompile
) können SieInternalLibrary
in Ihrem Anwendungscode darauf zugreifen :Auf diese Weise
MyLibrary
"verliert" das Modul möglicherweise die interne Implementierung von etwas. Sie sollten das nicht verwenden können, da es nicht direkt von Ihnen importiert wird.Die
implementation
Konfiguration wurde eingeführt, um dies zu verhindern. Also jetzt, wenn Sieimplementation
anstelle vonapi
in verwendenMyLibrary
:Sie können
InternalLibrary.giveMeAString()
Ihren App-Code nicht mehr aufrufen .Durch diese Art der Boxstrategie kann das Android Gradle-Plugin erkennen, dass beim Bearbeiten
InternalLibrary
nur die NeukompilierungMyLibrary
und nicht die Neukompilierung Ihrer gesamten App ausgelöst werden muss , da Sie keinen Zugriff darauf habenInternalLibrary
.Wenn Sie viele verschachtelte Abhängigkeiten haben, kann dieser Mechanismus den Build erheblich beschleunigen. (Sehen Sie sich das am Ende verlinkte Video an, um dies vollständig zu verstehen.)
SCHLUSSFOLGERUNGEN
Wenn Sie zum neuen Android Gradle-Plugin 3.XX wechseln, sollten Sie alle Ihre
compile
durch dasimplementation
Schlüsselwort (1 *) ersetzen . Versuchen Sie dann, Ihre App zu kompilieren und zu testen. Wenn alles in Ordnung ist, lassen Sie den Code unverändert. Wenn Sie Probleme haben, haben Sie wahrscheinlich einen Fehler mit Ihren Abhängigkeiten oder Sie haben etwas verwendet, das jetzt privat und nicht zugänglicher ist. Vorschlag von Android Gradle Plugin Ingenieur Jerome Dochez (1 ) * )Wenn Sie ein Bibliotheks-Mantainer sind, sollten Sie diese
api
für jede Abhängigkeit verwenden, die für die öffentliche API Ihrer Bibliothek benötigt wird, während Sie sieimplementation
für Testabhängigkeiten oder Abhängigkeiten verwenden, die von den Endbenutzern nicht verwendet werden dürfen.Nützlicher Artikel Den Unterschied zwischen Implementierung und API aufzeigen
REFERENZEN (Dies ist das gleiche Video, das aus Zeitgründen aufgeteilt wurde.)
Google I / O 2017 - Wie schnell Gradle erstellt wird (FULL VIDEO)
Google I / O 2017 - Wie schnell Gradle erstellt wird (NUR NEUES GRADLE PLUGIN 3.0.0-TEIL)
Google I / O 2017 - Beschleunigung der Erstellung von Gradle (Verweis auf 1 * )
Android-Dokumentation
quelle
MyLibrary#myString()
stürzt es ab, da ProGuardInternalLibrary
entfernt wurde. Was ist die beste Vorgehensweise für Android-Bibliotheken zur Verwendung in ProGuard-Apps?Ich denke gerne an eine
api
Abhängigkeit als öffentlich (von anderen Modulen gesehen) und eineimplementation
Abhängigkeit als privat (nur von diesem Modul gesehen).Beachten Sie, dass im Gegensatz zu
public
/private
Variablen und Methodenapi
/implementation
Abhängigkeiten von der Laufzeit nicht erzwungen werden. Dies ist lediglich eine Optimierung der Erstellungszeit, mit der ermittelt werden kannGradle
, welche Module neu kompiliert werden müssen, wenn eine der Abhängigkeiten ihre API ändert.quelle
api
Abhängigkeiten in den Bereich "Kompilieren" (sie werden als Abhängigkeiten in Ihre Bibliothek aufgenommen und alles, was von Ihrer Bibliothek abhängt) undimplementation
Abhängigkeiten in den Bereich "Laufzeit" (sie sind besser in den Bereich " Klassenpfad, wenn Ihr Code ausgeführt wird, aber nicht benötigt wird, um anderen Code zu kompilieren, der Ihre Bibliothek verwendet.implementation
für alle Abhängigkeiten verwenden, die zum Ausführen erforderlich sind (und für das Kompilieren Ihrer Bibliothek), aber nicht automatisch in Projekte gezogen werden sollten, die Ihre Bibliothek verwenden. Ein Beispiel wäre jax-rs. Ihre Bibliothek verwendet möglicherweise RESTeasy, sollte diese Bibliotheken jedoch nicht in ein Projekt ziehen, das Ihre Bibliothek verwendet, da sie möglicherweise stattdessen Jersey verwenden möchten.Betrachten Sie
app
Modul , das verwendetlib1
als Bibliothek undlib1
Verwendungenlib2
als Bibliothek. So etwas wie das :app -> lib1 -> lib2
.Jetzt bei der Verwendung von
api lib2
inlib1
, dannapp
sehenlib2
Codes bei der Verwendung von :api lib1
oderimplementation lib1
imapp
Modul.ABER bei Verwendung
implementation lib2
inlib1
kann dann die Codesapp
nicht sehenlib2
.quelle
Die Antworten von @matpag und @ dev-bmax sind klar genug, damit die Benutzer unterschiedliche Verwendungen zwischen Implementierung und API verstehen. Ich möchte nur eine zusätzliche Erklärung aus einem anderen Blickwinkel geben und hoffe, Menschen zu helfen, die die gleiche Frage haben.
Ich habe zwei Projekte zum Testen erstellt:
Die oben beschriebene Abhängigkeitshierarchie sieht folgendermaßen aus:
[Projekt-b] -> [Projekt-a] -> [Spring-Boot-Gradle-Plugin]
Dann habe ich folgende Szenarien getestet:
Das Erstellen von Projekt A hängt von 'org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE' durch Implementierung ab .
Führen Sie den
gradle dependencies
Befehl in einem Terminal im Stammverzeichnis von Objekt B aus. Mit dem folgenden Screenshot der Ausgabe können wir sehen, dass 'spring-boot-gradle-plugin' im Abhängigkeitsbaum von runtimeClasspath angezeigt wird, aber nicht in compileClasspath Die Verwendung einer Bibliothek, die mithilfe der Implementierung deklariert wurde, erfolgt nur nicht durch Kompilierung.Das Erstellen von Projekt A hängt von 'org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE' von api ab
Führen Sie den
gradle dependencies
Befehl in einem Terminal im Stammverzeichnis von Objekt B erneut aus. Jetzt wird 'spring-boot-gradle-plugin' sowohl im compileClasspath- als auch im runtimeClasspath-Abhängigkeitsbaum angezeigt.Ein wesentlicher Unterschied, den ich bemerkt habe, ist, dass die Abhängigkeit im Produzenten- / Bibliotheksprojekt, die auf Implementierungsart deklariert wurde, nicht in compileClasspath von Verbraucherprojekten angezeigt wird, so dass wir die entsprechende Bibliothek in den Verbraucherprojekten nicht verwenden können.
quelle
Aus der Gradle-Dokumentation :
Schauen wir uns ein sehr einfaches Build-Skript für ein JVM-basiertes Projekt an.
quelle