Staram się zrozumieć to, co jest różnica między api
i implementation
konfiguracja budując moje zależności.
W dokumentacji napisano, że implementation
ma to lepszy czas kompilacji, ale widząc ten komentarz w podobnym pytaniu, zastanawiałem się, czy to prawda.
Ponieważ nie jestem ekspertem od stopni, mam nadzieję, że ktoś może pomóc. Przeczytałem już dokumentację, ale zastanawiałem się nad łatwym do zrozumienia wyjaśnieniem.
android
gradle
dependencies
implementation
reinaldomoreira
źródło
źródło
compile
naapi
. Biblioteki, których używasz wewnętrznie, mogą wykorzystywać niektóre prywatne implementacje, które nie są ujawniane w bibliotece końcowej, więc są dla Ciebie przezroczyste. Te zależności „wewnętrzne-prywatne” można przełączyć na,implementation
a gdy wtyczka stopniowania Androida skompiluje twoją aplikację, pominie kompilację tych zależności, co skróci czas kompilacji (ale te zależności będą dostępne w czasie wykonywania). Oczywiście możesz zrobić to samo, jeśli masz lokalne biblioteki modułówOdpowiedzi:
Słowo
compile
kluczowe Gradle zostało wycofane na rzecz słów kluczowychapi
i,implementation
aby skonfigurować zależności.Korzystanie
api
jest równoznaczne z wykorzystaniem przestarzałecompile
, więc jeśli zastąpić wszystkocompile
zeapi
wszystko będzie działa jak zawsze.Aby zrozumieć
implementation
słowo kluczowe, rozważ następujący przykład.PRZYKŁAD
Załóżmy, że masz bibliotekę o nazwie,
MyLibrary
która wewnętrznie korzysta z innej biblioteki o nazwieInternalLibrary
. Coś takiego:Załóżmy, że konfiguracja
MyLibrary
build.gradle
zastosowań wygląda następująco:api
dependencies{}
Chcesz użyć
MyLibrary
w swoim kodzie, więc w swojej aplikacjibuild.gradle
dodajesz tę zależność:Za pomocą
api
konfiguracji (lub przestarzałejcompile
) możesz uzyskać dostępInternalLibrary
do kodu aplikacji:W ten sposób moduł
MyLibrary
potencjalnie „przecieka” wewnętrzną implementację czegoś. Nie powinieneś (być w stanie) tego używać, ponieważ nie jest on bezpośrednio importowany przez Ciebie.implementation
Konfiguracja została wprowadzona, aby temu zapobiec. Więc teraz, jeśli użyjeszimplementation
zamiastapi
wMyLibrary
:nie będziesz już mógł wywoływać
InternalLibrary.giveMeAString()
kodu aplikacji.Ten rodzaj strategii bokserskiej pozwala wtyczce Android Gradle wiedzieć, że jeśli coś edytujesz
InternalLibrary
, musi ona tylko wyzwalać ponowną kompilację,MyLibrary
a nie ponowną kompilację całej aplikacji, ponieważ nie masz do niej dostępuInternalLibrary
.Gdy masz wiele zagnieżdżonych zależności, ten mechanizm może znacznie przyspieszyć kompilację. (Obejrzyj film na końcu, aby w pełni to zrozumieć)
WNIOSKI
Po przełączeniu na nowy Android Gradle wtyczki 3.xx, należy wymienić wszystkie Twoje
compile
zeimplementation
słów kluczowych (1 *) . Następnie spróbuj skompilować i przetestować aplikację. Jeśli wszystko jest w porządku, pozostaw kod bez zmian, jeśli masz problemy, prawdopodobnie masz coś nie tak z zależnościami lub użyłeś czegoś, co teraz jest prywatne i nie jest bardziej dostępne. Sugestia inżyniera wtyczki Android Gradle Jerome Dochez (1 ) * )Jeśli jesteś mantainerem biblioteki, powinieneś używać go
api
do każdej zależności, która jest potrzebna dla publicznego interfejsu API twojej biblioteki, podczas gdyimplementation
do testowania zależności lub zależności, które nie mogą być używane przez użytkowników końcowych.Przydatny artykuł Przedstawienie różnicy między implementacją a interfejsem API
REFERENCJE (To samo wideo podzielone w celu zaoszczędzenia czasu)
Google I / O 2017 - Jak przyspieszyć kompilację Gradle (PEŁNE WIDEO)
Google I / O 2017 - Jak przyspieszyć kompilację Gradle (TYLKO NOWA GRADLE PLUGIN 3.0.0
Google I / O 2017 - Jak przyspieszyć kompilacje Gradle (odniesienie do 1 * )
Dokumentacja Androida
źródło
MyLibrary#myString()
ulegnie awarii, ponieważ ProGuard zostanieInternalLibrary
usunięty. Jaka jest najlepsza praktyka dla bibliotek z systemem Android w aplikacjach ProGuard?Lubię myśleć o
api
zależności jako publicznej (widzianej przez inne moduły), podczas gdyimplementation
zależność jako prywatnej (widzianej tylko przez ten moduł).Zauważ, że w przeciwieństwie do
public
/private
zmiennych i metod,api
/implementation
zależności nie są wymuszane przez środowisko wykonawcze. Jest to jedynie optymalizacja czasu kompilacji, która pozwalaGradle
dowiedzieć się, które moduły należy ponownie skompilować, gdy jedna z zależności zmieni interfejs API.źródło
api
zależności w zakresie „kompilacji” (zostaną one uwzględnione jako zależności w bibliotece i wszystko, co zależy od biblioteki) orazimplementation
zależności w zakresie „środowiska wykonawczego” (lepiej być w ścieżka klasy, gdy kod jest uruchomiony, ale nie są one potrzebne do kompilacji innego kodu korzystającego z biblioteki).implementation
do wszelkich zależności, które są wymagane do uruchomienia (i do skompilowania biblioteki), ale nie powinno się to automatycznie przeciągać do projektów korzystających z twojej biblioteki. Przykładem może być jax-rs, twoja biblioteka może korzystać z RESTeasy, ale nie powinna wciągać tych bibliotek do żadnego projektu korzystającego z twojej biblioteki, ponieważ zamiast tego mogą chcieć użyć Jersey.Rozważ, że masz
app
moduł, który używalib1
jako biblioteki ilib1
używalib2
jako biblioteki. Coś takiego:app -> lib1 -> lib2
.Teraz podczas używania
api lib2
wlib1
, a następnieapp
można zobaczyćlib2
kody przy użyciu:api lib1
lubimplementation lib1
wapp
module.Jednak przy użyciu
implementation lib2
wlib1
, toapp
nie widzę tychlib2
kodów.źródło
Odpowiedzi z @matpag i @ dev-bmax są wystarczająco jasne, aby ludzie zrozumieli różne zastosowania między implementacją a interfejsem API. Chcę tylko zrobić dodatkowe wyjaśnienie z innej strony, mam nadzieję pomóc ludziom, którzy mają to samo pytanie.
Stworzyłem dwa projekty do testowania:
Hierarchia zależności opisana powyżej wygląda następująco:
[project-b] -> [project-a] -> [spring-boot-gradle-plugin]
Następnie przetestowałem następujące scenariusze:
Sprawdź, czy projekt A zależy od „org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE” według implementacji .
Uruchom
gradle dependencies
polecenie w terminalu w katalogu głównym obiektu B po wyrzuceniu, po następującym zrzucie ekranu możemy zobaczyć, że „wiosna-boot-gradle-plugin” pojawia się w drzewie zależności runtimeClasspath, ale nie w compileClasspath, myślę, że właśnie dlatego nie możemy zrobić korzystanie z biblioteki, która zadeklarowała użycie implementacji, po prostu nie przejdzie kompilacji.Utwórz projekt A w zależności od 'org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE' przez api
gradle dependencies
Ponownie uruchom polecenie w terminalu w katalogu głównym katalogu B obiektu. Teraz „Spring-boot-gradle-plugin” pojawia się zarówno w drzewie zależności compileClasspath, jak i runtimeClasspath.Znaczącą różnicę, którą zauważyłem, jest to, że zależność w projekcie producenta / biblioteki zadeklarowana w sposób implementacji nie pojawi się w ścieżce compileClas projektów konsumenckich, więc nie możemy korzystać z odpowiedniej biblioteki lib w projektach konsumenckich.
źródło
Z dokumentacji stopnia :
Rzućmy okiem na bardzo prosty skrypt kompilacji dla projektu opartego na JVM.
źródło