В чем разница между реализацией и компиляцией в 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

С документация Gradle в:

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 библиотеки, в то время как конфигурация реализации должна использоваться для объявления зависимости, которые являются внутренними для деталь.

для дальнейшего объяснения обратитесь к этому изображению. Brief explanation


Краткое Решение:

лучший подход-заменить все 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 для всестороннего примера.