¿Cuál es la diferencia entre la implementación y la comstackción en Gradle?

Después de actualizar a Android Studio 3.0 y crear un nuevo proyecto, noté que en build.gradle hay una nueva forma de agregar nuevas dependencias en lugar de compile hay implementation y en lugar de testCompile hay testImplementation .

Ejemplo:

  implementation 'com.android.support:appcompat-v7:25.0.0' testImplementation 'junit:junit:4.12' 

en lugar de

  compile 'com.android.support:appcompat-v7:25.0.0' testCompile 'junit:junit:4.12' 

¿Cuál es la diferencia entre ellos y qué debería estar usando?

tl; dr

Simplemente reemplace:

  • compile con implementation
  • testCompile con testImplementation
  • debugCompile con debugImplementation
  • androidTestCompile con androidTestImplementation
  • compileOnly es valido Se agregó en 3.0 para reemplazar proporcionado y no comstackr. ( provided introducido cuando Gradle no tenía un nombre de configuración para ese caso de uso y lo nombró según el scope provisto por Maven).

Es uno de los cambios de última hora que viene con Gradle 3.0 que Google anunció en IO17 .

La configuración de compile ahora está en desuso y debe ser reemplazada por la implementation o api

De la documentación de Gradle :

 dependencies { api 'commons-httpclient:commons-httpclient:3.1' implementation 'org.apache.commons:commons-lang3:3.5' } 

Las dependencias que aparecen en las configuraciones de api se verán transitoriamente expuestas a los consumidores de la biblioteca y, como tales, aparecerán en la ruta de comstackción de clases de los consumidores.

Las dependencias que se encuentran en la configuración de implementation , por otro lado, no estarán expuestas a los consumidores y, por lo tanto, no se filtrarán en el classpath de comstackción de los consumidores. Esto viene con varios beneficios:

  • las dependencias ya no se filtran en la ruta de comstackción de clase de los consumidores, por lo que nunca dependerá accidentalmente de una dependencia transitiva
  • comstackción más rápida gracias al tamaño reducido de classpath
  • menos recomstackciones cuando cambian las dependencias de implementación: los consumidores no necesitarían ser recomstackdos
  • Publicación más limpia: cuando se utiliza junto con el nuevo complemento maven-publish, las bibliotecas Java producen archivos POM que distinguen exactamente entre lo que se requiere comstackr contra la biblioteca y lo que se requiere para usar la biblioteca en tiempo de ejecución (en otras palabras, no mezcle lo que se necesita para comstackr la biblioteca y lo que se necesita para comstackr contra la biblioteca).

La configuración de comstackción aún existe, pero no debe utilizarse, ya que no ofrecerá las garantías que proporcionan la api y implementation configuraciones de implementation .


Nota: si solo está utilizando una biblioteca en su módulo de aplicación, el caso común, no notará ninguna diferencia.
solo verá la diferencia si tiene un proyecto complejo con módulos que dependen el uno del otro, o si está creando una biblioteca.

Esta respuesta demostrará la diferencia entre implementation , api y compile en un proyecto. Digamos que tengo un proyecto con tres módulos de Gradle:

  • aplicación (una aplicación de Android)
  • myandroidlibrary (una biblioteca de Android)
  • myjavalibrary (una biblioteca de Java)

app tiene myandroidlibrary como dependencias. myandroidlibrary tiene myjavalibrary como dependencias.

aplicación -> myandroidlibrary -> myjavalibrary

myjavalibrary tiene una clase MySecret

 public class MySecret { public static String getSecret() { return "Money"; } } 

myandroidlibrary tiene MyAndroidComponent clase MyAndroidComponent que manipula el valor de la clase MySecret .

 public class MyAndroidComponent { private static String component = MySecret.getSecret(); public static String getComponent() { return "My component: " + component; } } 

Por último, la app solo está interesada en el valor de myandroidlibrary

 TextView tvHelloWorld = findViewById(R.id.tv_hello_world); tvHelloWorld.setText(MyAndroidComponent.getComponent()); 

Ahora, hablemos de las dependencias de la app build.gradle. Es muy simple e intuitivo.

 dependencies { implementation project(':myandroidlibrary') } 

¿ myandroidlibrary crees que debería parecer myandroidlibrary build.gradle? Tenemos tres opciones:

 dependencies { // Option #1 implementation project(':myjavalibrary') // Option #2 compile project(':myjavalibrary') // Option #3 api project(':myjavalibrary') } 

¿Cuál es la diferencia entre ellos y qué debería estar usando?

Comstackr y Api

Si está utilizando compile y api . Nuestra aplicación para Android ahora puede acceder a la dependencia myandroidcomponent , que es una clase MySecret .

 TextView textView = findViewById(R.id.text_view); textView.setText(MyAndroidComponent.getComponent()); // You can access MySecret textView.setText(MySecret.getSecret()); 

Implementación

Si está utilizando la configuración de implementation , MySecret no está expuesto.

 TextView textView = findViewById(R.id.text_view); textView.setText(MyAndroidComponent.getComponent()); // You can NOT access MySecret textView.setText(MySecret.getSecret()); // Won't even compile 

Entonces, ¿qué configuración debe elegir? Eso realmente depende de tu requerimiento.

Si desea exponer dependencias use api o compile , si no desea exponer las dependencias (ocultando su módulo interno) entonces use la implementation .

Esta es solo una parte esencial de las configuraciones de Gradle, consulte la Tabla 49.1. Complemento de biblioteca de Java: configuraciones utilizadas para declarar dependencias para una explicación más detallada.

El proyecto de muestra para esta respuesta está disponible en https://github.com/aldoKelvianto/ImplementationVsCompile

Compile configuración de Compile quedó en desuso y debe ser reemplazada por la implementation o api .

Puede leer los documentos en https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation .

La parte breve es-

La diferencia clave entre el plugin estándar de Java y el plugin de la biblioteca Java es que este último introduce el concepto de una API expuesta a los consumidores. Una biblioteca es un componente de Java destinado a ser consumido por otros componentes. Es un caso de uso muy común en las comstackciones de proyectos múltiples, pero también tan pronto como tenga dependencias externas.

El complemento expone dos configuraciones que se pueden usar para declarar dependencias: api e implementación. La configuración de la API se debe usar para declarar las dependencias que exporta la API de la biblioteca, mientras que la configuración de la implementación se debe usar para declarar las dependencias que son internas al componente.

Para una explicación más detallada, consulte esta imagen. Breve explicacion

Breve solución:

El mejor enfoque es reemplazar todas las dependencias de compile con dependencias de implementation . Y solo donde se filtra la interfaz de un módulo, debe usar api . Eso debería causar mucha menos recomstackción.

  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' }) } 

Explica más:

Antes de Android Gradle Plugin 3.0 : tuvimos un gran problema: un cambio de código causa la recomstackción de todos los módulos. La causa principal de esto es que Gradle no sabe si filtra la interfaz de un módulo a través de otro o no.

Después de Android Gradle Plugin 3.0 : el último complemento de Android Gradle ahora requiere que definas explícitamente si pierdes la interfaz de un módulo. En función de eso, puede tomar la decisión correcta sobre qué debería recomstackr.

Como tal, la dependencia de compile ha quedado en desuso y reemplazada por dos nuevas:

  • api : se filtra la interfaz de este módulo a través de su propia interfaz, lo que significa exactamente lo mismo que la antigua dependencia de compile

  • implementation : solo utiliza este módulo internamente y no lo filtra a través de su interfaz

Entonces ahora puede decirle explícitamente a Gradle que recompile un módulo si la interfaz de un módulo usado cambia o no.

Cortesía del blog de Jeroen Mols

La breve diferencia en el término del laico es:

  • Si está trabajando en una interfaz o módulo que brinda soporte a otros módulos al exponer a los miembros de la dependencia declarada, debe usar ‘api’.
  • Si está haciendo una aplicación o módulo que implementará o usará la dependencia declarada internamente, use ‘implementación’.
  • ‘comstackr’ funcionó igual que ‘api’, sin embargo, si solo está implementando o usando cualquier biblioteca, la ‘implementación’ funcionará mejor y le ahorrará recursos.

lea la respuesta de @aldok para un ejemplo completo.