with test studio replaced has compile been androidtestapi and android gradle android-studio build.gradle dependency-management gradle-plugin transitive-dependency

studio - configuration androidtestapi is obsolete and has been replaced with android test implementation



¿Cuál es la diferencia entre implementación y compilación en Gradle? (6)

Esta respuesta demostrará la diferencia entre implementation , api y compile en un proyecto.

Digamos que tengo un proyecto con tres módulos 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.

myjavalibrary tiene una clase MySecret

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

myandroidlibrary tiene la 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 ...

app necesita consumir :myandroidlibrary , por lo que en la app build.gradle usa la implementation .

( Nota : también puedes usar api / compile. Pero mantén ese pensamiento por un momento).

dependencies { implementation project('':myandroidlibrary'') }

¿ myandroidlibrary crees que debería verse myandroidlibrary build.gradle? ¿Qué alcance debemos usar?

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é debo usar?

Compilar o API (opción # 2 o # 3)

Si está utilizando compile o api . Nuestra aplicación de 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 (opción # 1)

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 su requerimiento.

Si desea exponer dependencias, use api o compile .

Si no desea exponer dependencias (ocultar su módulo interno), use la implementation .

Nota:

Esto es solo una esencia de las configuraciones de Gradle, consulte la Tabla 49.1. Complemento de la Biblioteca 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

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 vez de

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

¿Cuál es la diferencia entre ellos y qué debo usar?


Compile configuración de Compile ha quedado obsoleta y debe reemplazarse por implementation o api .

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

La breve parte es-

La diferencia clave entre el complemento estándar de Java y el complemento 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 compilaciones 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 debe usarse para declarar dependencias que son exportadas por la API de la biblioteca, mientras que la configuración de implementación debe usarse para declarar dependencias que son internas al componente.

Para más explicaciones, consulte esta imagen.


Breve solución:

El mejor enfoque es reemplazar todas las dependencias de compile con dependencias de implementation . Y solo cuando pierda la interfaz de un módulo, debe usar api . Eso debería causar mucha menos recompilació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 hace que todos los módulos se vuelvan a compilar. La causa raíz de esto es que Gradle no sabe si se pierde la interfaz de un módulo a través de otro o no.

Después del complemento Android Gradle 3.0 : el último complemento Android Gradle ahora requiere que defina explícitamente si pierde la interfaz de un módulo. En base a eso, puede tomar la decisión correcta sobre lo que debería compilar.

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

  • api : 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 usa 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 de laico es:

  • Si está trabajando en una interfaz o módulo que proporciona soporte a otros módulos al exponer a los miembros de la dependencia indicada, debería usar ''api''.
  • Si está creando una aplicación o módulo que va a implementar o usar internamente la dependencia indicada, use ''implementación''.
  • ''compilar'' funcionó igual que ''api'', sin embargo, si solo está implementando o utilizando cualquier biblioteca, ''implementación'' funcionará mejor y le ahorrará recursos.

lea la respuesta de @aldok para obtener un ejemplo completo.


tl; dr

Solo reemplace:

  • compile con implementation (si no necesita transitividad) o api (si necesita transitividad)
  • testCompile con testImplementation
  • debugCompile with debugImplementation
  • androidTestCompile con androidTestImplementation
  • compileOnly sigue siendo válido. Fue agregado en 3.0 para reemplazar provisto y no compilar. ( provided cuando Gradle no tenía un nombre de configuración para ese caso de uso y lo nombró por el alcance proporcionado por Maven).

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

La configuración de compile ahora está en desuso y debe reemplazarse por 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 la api estarán expuestas de forma transitiva a los consumidores de la biblioteca y, como tales, aparecerán en la compilación classpath de los consumidores.

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

  • las dependencias ya no se filtran en el classpath de compilación de los consumidores, por lo que nunca dependerá accidentalmente de una dependencia transitiva
  • compilación más rápida gracias al tamaño reducido de classpath
  • menos recompilaciones cuando cambian las dependencias de implementación: los consumidores no necesitarían ser recompilados
  • Publicación más limpia: cuando se usa junto con el nuevo complemento de publicación de Maven, las bibliotecas Java producen archivos POM que distinguen exactamente entre lo que se requiere para compilar contra la biblioteca y lo que se requiere para usar la biblioteca en tiempo de ejecución (en otras palabras, no mezclar lo que se necesita para compilar la biblioteca en sí y lo que se necesita para compilar contra la biblioteca).

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

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


+--------------------+----------------------+-------------+--------------+-----------------------------------------+ | Name | Role | Consumable? | Resolveable? | Description | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | api | Declaring | no | no | This is where you should declare | | | API | | | dependencies which are transitively | | | dependencies | | | exported to consumers, for compile. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | implementation | Declaring | no | no | This is where you should | | | implementation | | | declare dependencies which are | | | dependencies | | | purely internal and not | | | | | | meant to be exposed to consumers. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | compileOnly | Declaring compile | yes | yes | This is where you should | | | only | | | declare dependencies | | | dependencies | | | which are only required | | | | | | at compile time, but should | | | | | | not leak into the runtime. | | | | | | This typically includes dependencies | | | | | | which are shaded when found at runtime. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | runtimeOnly | Declaring | no | no | This is where you should | | | runtime | | | declare dependencies which | | | dependencies | | | are only required at runtime, | | | | | | and not at compile time. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | testImplementation | Test dependencies | no | no | This is where you | | | | | | should declare dependencies | | | | | | which are used to compile tests. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | testCompileOnly | Declaring test | yes | yes | This is where you should | | | compile only | | | declare dependencies | | | dependencies | | | which are only required | | | | | | at test compile time, | | | | | | but should not leak into the runtime. | | | | | | This typically includes dependencies | | | | | | which are shaded when found at runtime. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+ | testRuntimeOnly | Declaring test | no | no | This is where you should | | | runtime dependencies | | | declare dependencies which | | | | | | are only required at test | | | | | | runtime, and not at test compile time. | +--------------------+----------------------+-------------+--------------+-----------------------------------------+