tl; dr
Po prostu zamień:
compile
z implementation
(jeśli nie potrzebujesz przechodniości) lub api
(jeśli potrzebujesz przechodniości)
testCompile
z testImplementation
debugCompile
z debugImplementation
androidTestCompile
z androidTestImplementation
compileOnly
jest ciągle ważny. Został dodany w wersji 3.0 w celu zastąpienia pod warunkiem, a nie kompilacji. ( provided
wprowadzony, gdy Gradle nie miał nazwy konfiguracji dla tego przypadku użycia i nazwał ją na podstawie zakresu podanego przez Mavena).
Jest to jedna z przełomowych zmian wprowadzonych wraz z Gradle 3.0 ogłoszonym przez Google na IO17 .
compile
Konfiguracja jest teraz przestarzała i powinna zostać zastąpiona implementation
lubapi
Z dokumentacji Gradle :
dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}
Zależności pojawiające się w api
konfiguracjach zostaną tranzytowo udostępnione konsumentom biblioteki i jako takie pojawią się na ścieżce kompilacji konsumentów.
implementation
Z drugiej strony zależności znalezione w konfiguracji nie będą narażone na konsumentów, a zatem nie będą przeciekać ścieżki kompilacji klientów. Ma to kilka zalet:
- zależności nie przeciekają już do ścieżki kompilacji konsumentów, więc nigdy nie będziesz przypadkowo polegać na zależności przechodniej
- szybsza kompilacja dzięki zmniejszonemu rozmiarowi ścieżki klas
- mniej ponownych kompilacji, gdy zmieniają się zależności implementacyjne: konsumenci nie będą musieli ponownie kompilować
- czystsze publikowanie: w połączeniu z nową wtyczką maven-publishing biblioteki Java wytwarzają pliki POM, które dokładnie odróżniają to, co jest wymagane do skompilowania z biblioteką od tego, co jest wymagane do korzystania z biblioteki w czasie wykonywania (innymi słowy, nie wymieszać to, co jest potrzebne do skompilowania samej biblioteki i co jest potrzebne do skompilowania z biblioteką).
Konfiguracja kompilacji nadal istnieje, ale nie należy jej używać, ponieważ nie zapewnia ona gwarancji zapewnianych przez konfiguracje api
i implementation
.
Uwaga: jeśli używasz tylko biblioteki w module aplikacji - częsty przypadek - nie zauważysz żadnej różnicy.
zobaczysz różnicę tylko wtedy, gdy masz złożony projekt z modułami zależnymi od siebie lub tworzysz bibliotekę.
implementation
ukrywania zależności. Czy moje pytanie ma sens?implementation
tylko x api, zostanie odkryte, ale jeśli użyjeszapi
y, z również będzie widoczne.Ta odpowiedź będzie wykazać różnicę między
implementation
,api
orazcompile
nad projektem.Powiedzmy, że mam projekt z trzema modułami Gradle:
app
mamyandroidlibrary
jako zależności.myandroidlibrary
mamyjavalibrary
jako zależności.myjavalibrary
maMySecret
klasęmyandroidlibrary
maMyAndroidComponent
klasę, która manipuluje wartością zMySecret
klasy.Wreszcie
app
interesuje się tylko wartością zmyandroidlibrary
Porozmawiajmy teraz o zależnościach ...
app
trzeba konsumować:myandroidlibrary
, więc wapp
build.gradle użyjimplementation
.( Uwaga : możesz również użyć interfejsu API / kompilacji. Ale przytrzymaj tę myśl przez chwilę.)
Jak myślisz, jak
myandroidlibrary
powinna wyglądać build.gradle? Z jakiego zakresu powinniśmy korzystać?Mamy trzy opcje:
Kompiluj lub API (opcja nr 2 lub nr 3)
Jeśli używasz
compile
lubapi
. Nasza aplikacja na Androida ma teraz dostęp domyandroidcomponent
zależności, która jestMySecret
klasą.Realizacja (opcja nr 1)
Jeśli używasz
implementation
konfiguracji,MySecret
nie jest narażony.Którą konfigurację wybrać? To naprawdę zależy od twoich wymagań.
Jeśli chcesz ujawnić zależności, użyj
api
lubcompile
.Jeśli nie chcesz ujawniać zależności (ukrywanie modułu wewnętrznego), użyj
implementation
.Uwaga:
To tylko streszczenie konfiguracji Gradle, patrz Tabela 49.1. Wtyczka Java Library - konfiguracje używane do deklarowania zależności w celu uzyskania bardziej szczegółowych wyjaśnień.
Przykładowy projekt dla tej odpowiedzi jest dostępny na https://github.com/aldoKelvianto/ImplementationVsCompile
źródło
compile
nie gwarantuje tych samychapi
gwarancji.Compile
konfiguracja była przestarzała i powinna zostać zastąpiona przezimplementation
lubapi
.Dokumenty możesz przeczytać na https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation .
Krótka część jest-
Dalsze objaśnienia znajdują się w tym obrazie.
źródło
Krótkie rozwiązanie:
Lepszym rozwiązaniem jest zastąpienie wszystkich
compile
zależnościimplementation
zależnościami. I tylko w przypadku wycieku z interfejsu modułu, powinieneś użyćapi
. To powinno spowodować znacznie mniejszą rekompilację.Wyjaśnij więcej:
Przed Androidem Gradle plugin 3.0 : mieliśmy duży problem - jedna zmiana kodu powoduje rekompilację wszystkich modułów. Główną przyczyną tego jest to, że Gradle nie wie, czy przeciekasz interfejs modułu przez inny, czy nie.
Po Androidzie Gradle plugin 3.0 : najnowsza wtyczka Android Gradle wymaga teraz jawnego zdefiniowania, czy nieszczelność interfejsu modułu. Na tej podstawie może dokonać właściwego wyboru na podstawie tego, co powinien ponownie skompilować.
W związku z tym
compile
zależność została uznana za przestarzałą i zastąpiona dwoma nowymi:api
: przeciekasz interfejs tego modułu przez własny interfejs, co oznacza dokładnie to samo, co staracompile
zależnośćimplementation
: używasz tego modułu tylko wewnętrznie i nie przeciekasz go przez interfejsTeraz możesz teraz wyraźnie powiedzieć Gradleowi, aby ponownie skompilował moduł, jeśli interfejs używanego modułu zmieni się, czy nie.
Dzięki uprzejmości bloga Jeroen Mols
źródło
źródło
implementation
śledzęruntime
.Krótka różnica w terminach laika to:
przeczytaj odpowiedź @aldok, aby uzyskać wyczerpujący przykład.
źródło
Od wersji 5.6.3 dokumentacji Gradle zapewnia prostych zasad kciuk do identyfikacji czy starą
compile
zależność (lub nowy) należy zastąpićimplementation
lubapi
zależność:źródło
Gradle 3.0
wprowadzono kolejne zmiany:compile
->api
api
słowo kluczowe jest takie samo jak przestarzałecompile
compile
->implementation
Jest to preferowany sposób, ponieważ ma pewne zalety.
implementation
ujawniają zależność tylko o jeden poziom wyżej w czasie kompilacji (zależność jest dostępna w czasie wykonywania). W rezultacie masz szybszą kompilację (nie ma potrzeby ponownej kompilacji klientów, którzy są wyżej niż o 1 poziom wyżej)provided
->compileOnly
Ta zależność jest dostępna tylko w czasie kompilacji (zależność nie jest dostępna w czasie wykonywania). Ta zależność nie może być przechodnia i nią być
.aar
. Może być używany z procesorem adnotacji czasu kompilacji i pozwala zmniejszyć końcowy plik wyjściowycompile
->annotationProcessor
Bardzo podobny,
compileOnly
ale także gwarantuje, że zależność przechodnia nie będzie widoczna dla konsumentaapk
->runtimeOnly
Zależność nie jest dostępna w czasie kompilacji, ale jest dostępna w czasie wykonywania.
źródło
api = public
,implementation = internal
icompileOnly = private
- trzeba utworzyć takie aliasy dla tych funkcji, ponieważ są one bardzo mylące.