Я пытаюсь выяснить, в чем разница api
и implementation
конфигурация при построении моих зависимостей.
В документации говорится, что implementation
время сборки лучше, но, увидев этот комментарий в похожем вопросе, я удивился, правда ли это.
Так как я не специалист в Gradle, я надеюсь, что кто-то может помочь. Я уже прочитал документацию, но мне было интересно найти простое для понимания объяснение.
android
gradle
dependencies
implementation
reinaldomoreira
источник
источник
compile
наapi
. Библиотеки, которые вы используете внутри, могут использовать некоторые частные реализации, которые не представлены в конечной библиотеке, поэтому они прозрачны для вас. К этим «внутренним-частным» зависимостям можно переключиться,implementation
и когда плагин Android gradle скомпилирует ваше приложение, он пропустит компиляцию этих зависимостей, что приведет к меньшему времени сборки (но эти зависимости будут доступны во время выполнения). Очевидно, вы можете сделать то же самое, если у вас есть локальные библиотеки модулейОтветы:
Gradle
compile
ключевого слово осуждалось в пользуapi
иimplementation
ключевых слов зависимостей конфигурационных.Использование
api
равнозначно использованию устаревшегоcompile
, поэтому, если вы замените всеcompile
наapi
все, все будет работать как всегда.Чтобы понять
implementation
ключевое слово, рассмотрим следующий пример.ПРИМЕР
Предположим, у вас есть библиотека с именем,
MyLibrary
которая внутренне использует другую библиотеку с именемInternalLibrary
. Что-то вроде этого:Предположим, что
MyLibrary
build.gradle
используетapi
конфигурациюdependencies{}
следующим образом:Вы хотите использовать
MyLibrary
в своем коде, поэтому в своем приложенииbuild.gradle
вы добавляете эту зависимость:Используя
api
конфигурацию (или устарелаcompile
), вы можете получить доступInternalLibrary
к коду вашего приложения:Таким образом, модуль
MyLibrary
потенциально «пропускает» внутреннюю реализацию чего-либо. Вы не должны (быть в состоянии) использовать это, потому что это непосредственно не импортировано вами.implementation
Конфигурация была введена , чтобы предотвратить это. Так что теперь, если вы используетеimplementation
вместоapi
вMyLibrary
:Вы больше не сможете
InternalLibrary.giveMeAString()
набирать код своего приложения.Этот вид боксерской стратегии позволяет плагину Android Gradle знать, что если вы что-то редактируете
InternalLibrary
, он должен запускать только перекомпиляцию,MyLibrary
а не перекомпиляцию всего вашего приложения, потому что у вас нет доступа к немуInternalLibrary
.Когда у вас много вложенных зависимостей, этот механизм может значительно ускорить сборку. (Посмотрите видео в конце для полного понимания)
ВЫВОДЫ
При переходе на новый Android Gradle плагин 3.xx, вы должны заменить все ваши
compile
сimplementation
ключевым словом (1 *) . Затем попробуйте скомпилировать и протестировать ваше приложение. Если все в порядке, оставьте код как есть, если у вас есть проблемы, возможно, у вас что-то не так с вашими зависимостями, или вы использовали что-то частное и не более доступное. Предложение от Android плагин Gradle Джером Dochez (1 ) * )Если вы являетесь управляющим библиотекой, вы должны использовать ее
api
для каждой зависимости, которая необходима для общедоступного API вашей библиотеки, аimplementation
для тестовых зависимостей или зависимостей, которые не должны использоваться конечными пользователями.Полезная статья, демонстрирующая разницу между реализацией и API
ССЫЛКИ (Это то же видео, разделенное для экономии времени)
Google I / O 2017 - Как ускорить сборку Gradle (ПОЛНОЕ ВИДЕО)
Google I / O 2017 - Как ускорить сборку Gradle (ТОЛЬКО ДЛЯ НОВОЙ GRADLE PLUGIN 3.0.0)
Google I / O 2017 - Как ускорить сборку Gradle (ссылка на 1 * )
Android документация
источник
MyLibrary#myString()
сбой, потому что ProGuard будетInternalLibrary
удален. Какова лучшая практика для Android-библиотек, которые будут использоваться в приложениях ProGuard?Мне нравится думать о
api
зависимости как общедоступной (видимой другими модулями), аimplementation
зависимость как частной (видимой только этим модулем).Обратите внимание, что в отличие от
public
/private
переменных и методовapi
/implementation
зависимости не применяются во время выполнения. Это просто оптимизация во время сборки, которая позволяетGradle
узнать, какие модули нужно перекомпилировать, когда одна из зависимостей меняет свой API.источник
api
зависимости в область «компиляции» (они будут включены в качестве зависимостей в вашу библиотеку и все, что зависит от вашей библиотеки) иimplementation
зависимости в область «времени выполнения» (они лучше должны быть в classpath, когда ваш код работает, но они не нужны для компиляции другого кода, который использует вашу библиотеку).implementation
любую зависимость, которая требуется для запуска (и для вашей библиотеки для компиляции), но она не должна автоматически включаться в проекты, которые используют вашу библиотеку. Примером может служить jax-rs, ваша библиотека может использовать RESTeasy, но она не должна втягивать эти библиотеки в любой проект, который использует вашу библиотеку, так как они могут захотеть использовать вместо этого Jersey.Предположим, у вас есть
app
модуль, который используетсяlib1
как библиотека иlib1
используетсяlib2
как библиотека. Что - то вроде этого:app -> lib1 -> lib2
.Теперь при использовании
api lib2
вlib1
, тоapp
можно увидетьlib2
коды при использовании:api lib1
илиimplementation lib1
вapp
модуле.НО при использовании
implementation lib2
вlib1
, тоapp
не можете увидеть наlib2
коды.источник
Ответы от @matpag и @ dev-bmax достаточно ясны, чтобы люди понимали различные способы использования реализации и API. Я просто хочу дать дополнительное объяснение под другим углом, надеясь помочь людям, которые имеют такой же вопрос.
Я создал два проекта для тестирования:
Описанная выше иерархия зависимостей выглядит следующим образом:
[project-b] -> [project-a] -> [spring-boot-gradle-plugin]
Затем я протестировал следующие сценарии:
Сделать проект A зависит от 'org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE' by реализацией .
Запустите
gradle dependencies
команду в терминале в корневой директории объекта B , со следующим снимком экрана: мы видим, что «spring-boot-gradle-plugin» появляется в дереве зависимостей runtimeClasspath, но не в compileClasspath, я думаю, именно поэтому мы не можем сделать использование библиотеки, которая объявляет использование реализации, она просто не будет компилироваться.Сделать проект A зависит от 'org.springframework.boot: spring-boot-gradle-plugin: 1.5.20.RELEASE' от api
Запустите
gradle dependencies
команду в терминале в проекте B root dir снова. Теперь 'spring-boot-gradle-plugin' появляется в дереве зависимостей compileClasspath и runtimeClasspath.Существенное отличие, которое я заметил, заключается в том, что зависимость в проекте «производитель / библиотека», объявленная способом реализации, не появится в compileClasspath потребительских проектов, поэтому мы не можем использовать соответствующую библиотеку в потребительских проектах.
источник
Из учебной документации :
Давайте посмотрим на очень простой скрипт сборки для проекта на основе JVM.
источник