Únete a ⁠ #Android11: The Beta Launch Show el 3 de junio.

Cómo usar funciones del lenguaje Java 8

Android Studio 3.0 y las versiones posteriores admiten todas las funciones del lenguaje Java 7 y un subconjunto de funciones del lenguaje Java 8 que varían según la versión de la plataforma. En esta página, se describen las funciones del lenguaje Java 8 que puedes usar, la manera de configurar correctamente tu proyecto para usarlas y los problemas conocidos que puedes experimentar. Además, mira el siguiente video para obtener una descripción general.

Nota: Cuando se desarrollan apps para Android, el uso de funciones del lenguaje Java 8 es opcional. Puedes mantener los valores de compatibilidad de origen y destino de tu proyecto en Java 7, pero debes usar JDK 8 para la compilación.

Android Studio proporciona compatibilidad integrada para el uso de ciertas funciones del lenguaje Java 8 y bibliotecas de terceros que las utilizan. Como se muestra en la Figura 1, la cadena de herramientas predeterminada implementa las funciones nuevas del lenguaje realizando transformaciones de código de bytes, con el nombre desugar, en el resultado del compilador javac. Ya no se admite Jack, y primero debes inhabilitarlo para usar la compatibilidad con Java 8, integrada en la cadena de herramientas predeterminada.

Figura 1: Compatibilidad con funciones del lenguaje Java 8 mediante transformaciones de código de bytes desugar

Para comenzar a usar las funciones del lenguaje Java 8 compatibles, actualiza el complemento para Android a 3.0.0 (o versiones posteriores). Luego, para cada módulo que use funciones del lenguaje Java 8 (ya sea en su código fuente o a través de dependencias), actualiza Source Compatibility y Target Compatibility a 1.8 en el diálogo Project Structure, como se muestra en la figura 2 (haz clic en File > Project Structure).

Figura 2: Compatibilidad con funciones del lenguaje Java 8 mediante transformaciones de código de bytes desugar

También puedes configurarlo directamente en el archivo build.gradle correspondiente:

android {
      ...
      // Configure only for each module that uses Java 8
      // language features (either in its source code or
      // through dependencies).
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
      // For Kotlin projects
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    

Nota: Si Android Studio detecta que tu proyecto usa Jack, Retrolambda o DexGuard, el IDE usará la compatibilidad con Java 8 provista por esas herramientas. Sin embargo, quizás te convenga realizar una migración a la cadena de herramientas predeterminada.

Funciones y API admitidas del lenguaje Java 8

Android Studio no admite todas las funciones del lenguaje Java 8, pero se agregarán más en las versiones futuras del IDE. Según la versión de minSdkVersion que uses, algunas funciones y API ya se encuentran disponibles, como se describe en la siguiente tabla.

Función del lenguaje Java 8 minSdkVersion compatible
Expresiones lambda Cualquiera. Ten en cuenta que Android no admite la serialización de expresiones lambda.
Referencias de métodos Cualquiera.
Anotaciones de tipos Cualquiera. Sin embargo, la información de anotaciones de tipos se encuentra disponible en el tiempo de compilación pero no en el de ejecución. Además, la plataforma admite TYPE en la API nivel 24 y versiones anteriores, pero no ElementType.TYPE_USE o ElementType.TYPE_PARAMETER.
Métodos de interfaz predeterminados y estáticos Cualquiera.
Repetición de anotaciones Cualquiera.
API del lenguaje Java 8 minSdkVersion compatible
java.lang.annotation.Repeatable API nivel 24 o versiones posteriores
AnnotatedElement.getAnnotationsByType(Class) API nivel 24 o versiones posteriores
java.util.stream API nivel 24 o versiones posteriores
java.lang.FunctionalInterface API nivel 24 o versiones posteriores
java.lang.reflect.Method.isDefault() API nivel 24 o versiones posteriores
java.util.function API nivel 24 o versiones posteriores

Además de las API y funciones del lenguaje Java 8, en Android Studio 3.0 y versiones posteriores se extiende la compatibilidad con todos los niveles de API de Android para try-with-resources.

Por el momento, Desugar no admite MethodHandle.invoke ni MethodHandle.invokeExact. Si tu código fuente o una de las dependencias de tu módulo usan uno de estos métodos, debes especificar minSdkVersion 26 o una versión posterior. De lo contrario, verás el siguiente error:

Dex: Error converting bytecode to dex:
    Cause: signature-polymorphic method called without --min-sdk-version >= 26
    

En algunos casos, es posible que tu módulo no use los métodos invoke ni invokeExact, incluso si forman parte de una dependencia de biblioteca. Por lo tanto, para seguir usando esa biblioteca con minSdkVersion 25 o versiones anteriores, habilita la reducción de código a fin de quitar los métodos sin utilizar. Si eso no funciona, considera usar una biblioteca alternativa que no emplee los métodos no admitidos.

Cómo migrar a la cadena de herramientas predeterminada

Si Android Studio detecta que tu proyecto usa Jack, Retrolambda o DexGuard, el IDE usará la compatibilidad con Java 8 que proporcionan esas herramientas. Sin embargo, en comparación con la cadena de herramientas predeterminadas, esas herramientas carecen de funcionalidad y compatibilidad. Por lo tanto, sigue las instrucciones de esta sección para realizar la migración a la cadena de herramientas predeterminada de Android Studio.

Cómo migrar desde Jack

La cadena de herramientas Jack dejó de estar disponible, de acuerdo con este anuncio. Si tu proyecto depende de Jack, debes realizar la migración para usar la compatibilidad con Java 8 integrada a la cadena de herramientas predeterminada de Android Studio, que también admite bibliotecas de terceros que usan funciones del lenguaje Java 8 y compatibilidad con herramientas que dependen de archivos .class intermedios.

Para inhabilitar Jack y cambiar a la cadena de herramientas predeterminada, solo tienes que quitar el bloque jackOptions del archivo build.gradle de tu módulo:

android {
        ...
        defaultConfig {
            ...
            // Remove this block.
            jackOptions {
                enabled true
                ...
            }
        }

        // Keep the following configuration in order to target Java 8.
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
        // For Kotlin projects
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    

Cómo migrar desde Retrolambda

En comparación con la cadena de herramientas predeterminada de Android Studio, Retrolambda no admite bibliotecas de terceros que usen funciones del lenguaje Java 8. Para realizar la migración a la cadena de herramientas predeterminada, quita la dependencia Retrolambda del archivo build.gradle de tu nivel de proyecto:

buildscript {
      ...
       dependencies {
          // Remove the following dependency.
          classpath 'me.tatarka:gradle-retrolambda:<version_number>'
       }
    }
    

También debes quitar el complemento para Retrolambda y el bloque retrolambda del archivo build.gradle de cada módulo:

    // Remove the following plugin.
    apply plugin: 'me.tatarka.retrolambda'
    ...
    // Remove this block after migrating useful configurations.
    retrolambda {
        ...
        // If you have arguments for the Java VM you want to keep,
        // move them to your project's gradle.properties file.
        jvmArgs '-Xmx2048m'
    }
    

Cómo inhabilitar la compatibilidad con funciones del lenguaje Java 8

Si experimentas problemas relacionados con la compatibilidad en funciones del lenguaje Java 8, puedes inhabilitarla agregando lo siguiente a tu archivo gradle.properties:

android.enableDesugar=false
    

Para ayudarnos a mejorar la compatibilidad con Java 8, informa cualquier error que encuentres.