В чем разница между реализацией и компиляцией в Gradle?
после обновления до Android Studio 3.0 и создание нового проекта, я заметил, что в build.gradle
существует новый способ добавления новых зависимостей вместо compile
здесь implementation
и вместо testCompile
здесь testImplementation
.
пример:
implementation 'com.android.support:appcompat-v7:25.0.0'
testImplementation 'junit:junit:4.12'
вместо
compile 'com.android.support:appcompat-v7:25.0.0'
testCompile 'junit:junit:4.12'
в чем разница между ними и что я должен использовать?
5 ответов
tl; dr
заменить:
-
compile
Сimplementation
-
testCompile
СtestImplementation
-
debugCompile
СdebugImplementation
-
androidTestCompile
СandroidTestImplementation
-
compileOnly
остается в силе. Он был добавлен в 3.0 для замены предоставленного, а не компиляции. (provided
введено, когда Gradle не имел имени конфигурации для этого прецедента и назвал его после предоставленного Maven масштаб.)
это одно из разрушительных изменений, приходящих с Gradle 3.0, что Google объявлено на IO17.
на compile
конфигурация теперь устаревший и должен быть заменен на implementation
или api
dependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.apache.commons:commons-lang3:3.5' }
зависимости, появляющиеся в
api
конфигурации будет транзитивное воздействие на потребителей библиотеки, и как таковой будет отображаются в пути к классам compile потребителей.зависимости, найденные в
implementation
настройки в с другой стороны, не подвергаться воздействию потребителей и, следовательно, не просачиваться в путь к классам компиляции потребителей. Это имеет несколько преимуществ:
- зависимости больше не просачиваются в путь классов компиляции потребителей, поэтому вы никогда случайно не будете зависеть от транзитивного зависимость
- быстрее компиляция благодаря уменьшенному размеру classpath
- меньше перекомпиляций при изменении зависимостей реализации: потребителям не нужно будет перекомпилировать
- cleaner publishing: при использовании в сочетании с новым плагином Maven-publish библиотеки Java создают файлы POM, которые различать точно между тем, что требуется для компиляции библиотека и то, что требуется для использования библиотеки во время выполнения (в другом слова, не смешивайте то, что необходимо для компиляции сама библиотека и что необходимо скомпилировать против библиотеки).
конфигурация компиляции все еще существует, но не должна использоваться, поскольку она не будет предлагать гарантии того, что
api
иimplementation
конфигурации обеспечивают.
Примечание: если вы используете только библиотеку в своем модуле приложения-общий случай-вы не заметите никакой разницы.
вы увидите разницу, только если у вас есть сложный проект с модулями в зависимости друг от друга, или вы создаете библиотеку.
этот ответ продемонстрирует разницу между implementation
, api
и compile
о проекте. Предположим, у меня есть проект с тремя модулями Gradle:
- app (приложение для Android)
- myandroidlibrary (библиотека Android)
- myjavalibrary (библиотека Java)
app
и myandroidlibrary
в качестве зависимостей. myandroidlibrary
и myjavalibrary
в качестве зависимостей.
app - > myandroidlibrary - > myjavalibrary
myjavalibrary
есть MySecret
класс
public class MySecret {
public static String getSecret() {
return "Money";
}
}
myandroidlibrary
и MyAndroidComponent
класс, который манипулирует значением из MySecret
класса.
public class MyAndroidComponent {
private static String component = MySecret.getSecret();
public static String getComponent() {
return "My component: " + component;
}
}
и наконец, app
интересует только значение myandroidlibrary
TextView tvHelloWorld = findViewById(R.id.tv_hello_world);
tvHelloWorld.setText(MyAndroidComponent.getComponent());
теперь поговорим о зависимостях от app
построить.градля. Это очень просто и интуитивно.
dependencies {
implementation project(':myandroidlibrary')
}
что думаете?myandroidlibrary
построить.Gradle в должен выглядеть? У нас их три. опции:
dependencies {
// Option #1
implementation project(':myjavalibrary')
// Option #2
compile project(':myjavalibrary')
// Option #3
api project(':myjavalibrary')
}
в чем разница между ними и что я должен использовать?
компиляция и Api
если вы используете compile
и api
. Наше приложение для Android теперь может получить доступ myandroidcomponent
зависимость, которая является MySecret
класса.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can access MySecret
textView.setText(MySecret.getSecret());
реализация
если вы используете implementation
конфигурации MySecret
не уязвимый.
TextView textView = findViewById(R.id.text_view);
textView.setText(MyAndroidComponent.getComponent());
// You can NOT access MySecret
textView.setText(MySecret.getSecret()); // Won't even compile
Итак, какую конфигурацию вы выберите? Это действительно зависит от вашего требования.
если вы хотите выставить зависимости, используйте api
или compile
, если вы не хотите выставлять зависимости (скрывая свой внутренний модуль), используйте implementation
.
это просто суть конфигураций Gradle, обратитесь к таблица 49.1. Плагин библиотеки Java-конфигурации, используемые для объявления зависимостей для получения более подробной объяснение.
пример проекта для этого ответа доступен на https://github.com/aldoKelvianto/ImplementationVsCompile
Compile
конфигурация устарела и должна быть заменена implementation
или api
.
вы можете прочитать документы на https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation.
В этой части-
ключевое различие между стандартным плагином Java и Java Плагин библиотеки заключается в том, что последний вводит понятие API подвергается воздействию потребителей. Библиотека-это Java компонент, предназначенный для потребляется другими компонентами. Это очень распространенный случай использования в мульти-проект строит, но и как только у вас есть внешний зависимости.
плагин предоставляет две конфигурации, которые можно использовать для объявления зависимости: api и реализация. Конфигурация api должна быть используется для объявления зависимостей, экспортируемых API библиотеки, в то время как конфигурация реализации должна использоваться для объявления зависимости, которые являются внутренними для деталь.
Краткое Решение:
лучший подход-заменить все compile
зависимости implementation
зависимостей. И только там, где вы пропускаете интерфейс модуля, вы должны использовать api
. Это должно вызвать гораздо меньшую перекомпиляцию.
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:25.4.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
// …
testImplementation 'junit:junit:4.12'
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
}
Объясню Подробнее:
перед Android Gradle плагин 3.0: у нас была большая проблема, которая является одним изменением кода вызывает перекомпиляцию всех модулей. Корень причина этого заключается в том, что Gradle не знает, протекает ли интерфейс модуля через другой или нет.
после Android Gradle плагин 3.0: последний плагин Android Gradle теперь требует, чтобы вы явно определили, если вы утечка интерфейса модуля. Исходя из этого, он может сделать правильный выбор о том, что он должен перекомпилировать.
как compile
зависимость устарела и заменена двумя новыми из них:
api
: вы пропускаете интерфейс этого модуля через свой собственный интерфейс, что означает точно так же, как старыйcompile
зависимостьimplementation
: вы используете этот модуль только внутри и не пропускаете его через свой интерфейс
теперь вы можете явно сказать Gradle перекомпилировать модуль, если интерфейс используемого модуля изменяется или нет.
вежливость Йерун Молс блог
краткое различие в термине непрофессионала:
- если вы работаете над интерфейсом или модулем, который обеспечивает поддержку других модулей, подвергая членов указанной зависимости, вы должны использовать "api".
- если вы создаете приложение или модуль, который собирается реализовать или использовать указанную зависимость внутри, используйте "реализация".
- 'compile' работал так же, как 'api', однако, если вы только реализуете или используете любая библиотека, "реализация" будет работать лучше и экономить ваши ресурсы.
прочитайте ответ @aldok для всестороннего примера.