tl; dr
Einfach ersetzen:
compile
mit implementation
(wenn Sie keine Transitivität benötigen) oder api
(wenn Sie Transitivität benötigen)
testCompile
mit testImplementation
debugCompile
mit debugImplementation
androidTestCompile
mit androidTestImplementation
compileOnly
Ist noch gültig. Es wurde in 3.0 hinzugefügt, um das bereitgestellte zu ersetzen und nicht zu kompilieren. ( provided
Eingeführt, als Gradle keinen Konfigurationsnamen für diesen Anwendungsfall hatte und ihn nach Mavens bereitgestelltem Bereich benannte.)
Dies ist eine der wichtigsten Änderungen, die mit Gradle 3.0 einhergehen und die Google auf der IO17 angekündigt hat .
Die compile
Konfiguration ist jetzt veraltet und sollte durch implementation
oder ersetzt werdenapi
Aus der Gradle-Dokumentation :
dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}
Abhängigkeiten, die in den api
Konfigurationen angezeigt werden, werden den Verbrauchern der Bibliothek transitiv ausgesetzt und als solche im Kompilierungsklassenpfad der Verbraucher angezeigt.
Abhängigkeiten, die in der implementation
Konfiguration gefunden werden, sind andererseits nicht für Verbraucher verfügbar und gelangen daher nicht in den Kompilierungsklassenpfad der Verbraucher. Dies hat mehrere Vorteile:
- Abhängigkeiten gelangen nicht mehr in den Kompilierungsklassenpfad von Verbrauchern, sodass Sie nie versehentlich von einer transitiven Abhängigkeit abhängig sind
- schnellere Kompilierung dank reduzierter Klassenpfadgröße
- weniger Neukompilierungen, wenn sich Implementierungsabhängigkeiten ändern: Verbraucher müssten nicht neu kompiliert werden
- Cleaner Publishing: In Verbindung mit dem neuen Maven-Publish-Plugin erstellen Java-Bibliotheken POM-Dateien, die genau unterscheiden, was zum Kompilieren mit der Bibliothek erforderlich ist und was zur Verwendung der Bibliothek zur Laufzeit erforderlich ist (mit anderen Worten, nicht mischen, was zum Kompilieren der Bibliothek selbst benötigt wird und was zum Kompilieren gegen die Bibliothek benötigt wird).
Die Kompilierungskonfiguration ist noch vorhanden, sollte jedoch nicht verwendet werden, da sie nicht die Garantien bietet, die die Konfigurationen api
und implementation
bieten.
Hinweis: Wenn Sie nur eine Bibliothek in Ihrem App-Modul verwenden - im allgemeinen Fall - werden Sie keinen Unterschied bemerken.
Sie werden den Unterschied nur sehen, wenn Sie ein komplexes Projekt mit voneinander abhängigen Modulen haben oder eine Bibliothek erstellen.
implementation
die Abhängigkeit zu verbergen. Ist meine Frage sinnvoll?implementation
nur x api verwenden, wird belichtet, aber wenn Sieapi
y verwenden, wird auch z belichtet.Diese Antwort wird den Unterschied zwischen demonstrieren
implementation
,api
undcompile
an einem Projekt.Angenommen, ich habe ein Projekt mit drei Gradle-Modulen:
app
hatmyandroidlibrary
als Abhängigkeiten.myandroidlibrary
hatmyjavalibrary
als Abhängigkeiten.myjavalibrary
hat eineMySecret
Klassemyandroidlibrary
hat eineMyAndroidComponent
Klasse, die den Wert derMySecret
Klasse manipuliert .Schließlich
app
interessiert sich nur der Wert vonmyandroidlibrary
Lassen Sie uns nun über Abhängigkeiten sprechen ...
app
müssen verbrauchen:myandroidlibrary
, also inapp
build.gradle verwendenimplementation
.( Hinweis : Sie können auch api / compile verwenden. Halten Sie diesen Gedanken jedoch einen Moment lang fest.)
Wie
myandroidlibrary
sollte build.gradle Ihrer Meinung nach aussehen? Welchen Bereich sollten wir verwenden?Wir haben drei Möglichkeiten:
Kompilieren oder API (Option 2 oder 3)
Wenn Sie
compile
oder verwendenapi
. Unsere Android-Anwendung kann jetzt auf diemyandroidcomponent
Abhängigkeit zugreifen , die eineMySecret
Klasse ist.Implementierung (Option 1)
Wenn Sie die
implementation
Konfiguration verwenden,MySecret
wird diese nicht angezeigt.Also, welche Konfiguration sollten Sie wählen? Das hängt wirklich von Ihrer Anforderung ab.
Wenn Sie Abhängigkeiten verfügbar machen möchten, verwenden Sie
api
odercompile
.Wenn Sie keine Abhängigkeiten verfügbar machen möchten (indem Sie Ihr internes Modul ausblenden), verwenden Sie
implementation
.Hinweis:
Dies ist nur ein Überblick über Gradle-Konfigurationen (siehe Tabelle 49.1). Java Library Plugin - Konfigurationen zum Deklarieren von Abhängigkeiten für detailliertere Erklärungen.
Das Beispielprojekt für diese Antwort ist unter https://github.com/aldoKelvianto/ImplementationVsCompile verfügbar
quelle
compile
nicht die gleichen Dingeapi
garantiert werden , die garantieren.Compile
Konfiguration war veraltet und sollte durchimplementation
oder ersetzt werdenapi
.Sie können die Dokumente unter https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation lesen .
Der kurze Teil ist:
Weitere Erläuterungen finden Sie in diesem Bild.
quelle
Kurze Lösung:
Der bessere Ansatz besteht darin, alle
compile
Abhängigkeiten durchimplementation
Abhängigkeiten zu ersetzen . Und nur dort, wo Sie die Schnittstelle eines Moduls verlieren, sollten Sie verwendenapi
. Das sollte viel weniger Neukompilierung verursachen.Erkläre mehr:
Vor dem Android Gradle Plugin 3.0 : Wir hatten ein großes Problem: Eine Codeänderung führt dazu, dass alle Module neu kompiliert werden. Die Hauptursache dafür ist, dass Gradle nicht weiß, ob Sie die Schnittstelle eines Moduls durch ein anderes lecken oder nicht.
Nach Android Gradle Plugin 3.0 : Für das neueste Android Gradle Plugin müssen Sie jetzt explizit definieren, ob Sie die Schnittstelle eines Moduls verlieren. Auf dieser Grundlage kann es die richtige Wahl treffen, was neu kompiliert werden soll.
Daher wurde die
compile
Abhängigkeit verworfen und durch zwei neue ersetzt:api
: Sie lecken die Schnittstelle dieses Moduls über Ihre eigene Schnittstelle, was genau der altencompile
Abhängigkeit entsprichtimplementation
: Sie verwenden dieses Modul nur intern und lecken es nicht über Ihre SchnittstelleJetzt können Sie Gradle explizit anweisen, ein Modul neu zu kompilieren, wenn sich die Schnittstelle eines verwendeten Moduls ändert oder nicht.
Mit freundlicher Genehmigung von Jeroen Mols Blog
quelle
quelle
implementation
von einem gefolgtruntime
.Der kurze Unterschied in der Amtszeit von Laien ist:
Lesen Sie die Antwort von @aldok für ein umfassendes Beispiel.
quelle
Seit Version 5.6.3 bietet die Gradle-Dokumentation einfache Faustregeln, um festzustellen, ob eine alte
compile
(oder eine neue) Abhängigkeit durch eineimplementation
oder eineapi
Abhängigkeit ersetzt werden sollte:quelle
Gradle 3.0
nächste Änderungen eingeführt:compile
->api
api
Schlüsselwort ist das gleiche wie veraltetcompile
compile
->implementation
Ist vorzuziehen , weil es einige Vorteile hat.
implementation
Stellen Sie die Abhängigkeit zur Erstellungszeit nur für eine Ebene höher bereit (die Abhängigkeit ist zur Laufzeit verfügbar). Als Ergebnis haben Sie einen schnelleren Build (Sie müssen keine Konsumenten neu kompilieren, die höher als 1 Stufe sind).provided
->compileOnly
Diese Abhängigkeit ist nur zur Kompilierungszeit verfügbar (die Abhängigkeit ist zur Laufzeit nicht verfügbar). Diese Abhängigkeit kann nicht transitiv sein und sein
.aar
. Es kann mit dem Annotationsprozessor zur Kompilierungszeit verwendet werden und ermöglicht es Ihnen, eine endgültige Ausgabedatei zu reduzierencompile
->annotationProcessor
Sehr ähnlich,
compileOnly
garantiert aber auch, dass die transitive Abhängigkeit für den Verbraucher nicht sichtbar istapk
->runtimeOnly
Die Abhängigkeit ist nicht zur Kompilierungszeit verfügbar, sondern zur Laufzeit.
quelle
api = public
,implementation = internal
undcompileOnly = private
- ich brauche solche Aliase für diese Funktionen zu erstellen , wie sie Super sind verwirrend.