7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Android SDK

Java 8 para Android: código más limpio con expresiones lambda

Scroll to top
Read Time: 16 mins
This post is part of a series called Java 8 for Android Development.
Java 8 for Android Development: Default and Static Methods

Spanish (Español) translation by Ana Paulina Figueroa (you can also view the original English article)

Las expresiones lambda pueden ayudarte a eliminar el código repetitivo de tus proyectos y procesar grandes cantidades de información con facilidad. Puedes ver cómo hacerlo con este análisis a profundidad de las características de Java 8 que puedes comenzar a usar en tus proyectos Android hoy mismo.

Java 8 para Android

Java 8, que debutó tiempo atrás en marzo de 2014, fue un gran paso hacia adelante para el lenguaje de programación, al introducir una lista de funciones que prometían hacer que la codificación en Java fuera más fácil y concisa que nunca.

Desafortunadamente, los desarrolladores de Android no sintieron los beneficios de estas características por un tiempo, ya que Google experimentó con el uso de Java 8 y la plataforma Android a través de Jack (Java Android Compiler Kit) antes de dejar de usar Jack en favor de la admisión de Java 8 de forma nativa en Android Studio.

Ahora, con el lanzamiento de Android Studio 3.0, finalmente tenemos una versión de la cadena de herramientas de Android que tiene compatibilidad incorporada con algunas de las funciones más importantes de Java 8.

En esta serie, te mostraré cómo eliminar una gran cantidad de código repetitivo de tus proyectos, cómo procesar grandes cantidades de datos con facilidad e incluso cómo adoptar un estilo más funcional en tu programación en Java usando Java 8. Examinaremos en profundidad las características de Java 8 que puedes comenzar a usar hoy mismo.

Para cuando hayas completado esta serie, estarás listo para usar todas las siguientes funciones de Java 8 en tus proyectos de Android:

  • expresiones lambda
  • referencias a métodos
  • métodos predeterminados
  • métodos de interfaz estática
  • anotaciones de tipo
  • anotaciones repetitivas
  • interfaces funcionales
  • la API Stream

En esta primera publicación, vamos a ver la herramienta que generó más expectativas cuando Java 8 fue lanzado por primera vez, y que tiene el potencial de marcar la mayor diferencia para los desarrolladores de Android: las expresiones lambda.

Preparación de tu entorno de desarrollo

Antes de que puedas comenzar a usar cualquier herramienta de Java 8, debes asegurarte de que tu entorno de desarrollo esté configurado para admitir esta versión de Java.

Si aún no tienes instalado Java 8, deberás descargar el JDK8 más reciente y actualizar la ruta del JDK de Android Studio para que apunte al paquete JDK8:

  • Ejecuta Android Studio.
  • Selecciona Archivo > Estructura del proyecto... desde la barra de herramientas de Android Studio.
  • Actualiza el campo Ubicación del JDK para que apunte al paquete JDK8 que recién descargaste.

Si no estás seguro de qué versión de Java tienes instalada, puedes verificar esta información abriendo una ventana de Terminal (si eres usuario de Mac) o un símbolo del sistema (si estás en Windows) y luego ejecutando el siguiente comando:

Si el comando devuelve la compilación 1.8 o posterior, ¡entonces estás listo para comenzar!

También deberás tener instalado Android Studio 3.0 Vista previa 1 o posterior, aunque para reducir las posibilidades de que te encuentres con errores y otros comportamientos extraños, es recomendable que instales la versión más reciente de Android Studio 3.0, ya sea una versión beta o una vista previa o, idealmente, una versión estable de Android Studio 3.0 (que aún no estaba disponible en el momento de escribir este artículo).

A continuación deberás realizar algunos cambios en los archivos build.gradle de tu proyecto. Por lo general, solamente necesitarás agregar algunas líneas de código para especificar que este proyecto debe generar código de bytes Java 8. Sin embargo, si has experimentado previamente con las características de Java 8 utilizando el compilador Jack o el popular proyecto Retrolambda, deberás deshabilitar estas herramientas antes de que tu proyecto pueda usar el nuevo y mejorado soporte de Java 8 proporcionado por la cadena de herramientas predeterminada de Android.

En las siguientes secciones, te mostraré cómo habilitar la compatibilidad con Java 8 y cómo deshabilitar Retrolambda y Jack, si es necesario.

Adición de compatibilidad con Java 8 a un nuevo proyecto

Suponiendo que no hayas habilitado Jack o agregado Retrolambda como dependencia del proyecto previamente, el primer paso es abrir tu archivo build.gradle a nivel de proyecto y asegurarte de que estés utilizando la versión 3.0.0-alpha1 (o posterior) del plugin Gradle para Android:

A continuación, abre todos los archivos build.gradle a nivel de módulo en los que quieras utilizar las herramientas de Java 8 y configura el nivel de lenguaje del código fuente y la versión del código de bytes Java generado con el valor JavaVersion.VERSION_1_8:

Si vas a migrar de Jack

El compilador Jack puede ser obsoleto, pero mientras esté habilitado, tu proyecto utilizará el soporte para Java 8 proporcionado por Jack en lugar del soporte proporcionado por la cadena de herramientas predeterminada de Android.

El uso de una herramienta obsoleta nunca es una buena idea, pero hay algunas razones adicionales por las que deberías migrar del compilador Jack, si aún no lo has hecho.

En primer lugar, Jack puede ser compatible con un subconjunto de herramientas de Java 8, pero a diferencia de la cadena de herramientas predeterminada, Jack no es compatible con bibliotecas de terceros que usen estas funciones. Por lo tanto, al usar Jack estás limitando inmediatamente tus opciones en cuanto a bibliotecas de terceros.

En segundo lugar, el compilador Jack toma código Java y lo convierte directamente en dex, sin producir ningún código de bytes intermedio. Mientras Jack esté habilitado, no podrás usar ninguna de las herramientas que dependen de esta salida intermedia, como los procesadores de anotaciones y los analizadores de código de bytes.

Para deshabilitar el compilador Jack, abre tu archivo build.gradle a nivel de módulo y elimina la sección jackOptions, pero asegúrate de dejar intacto el bloque compileOptions:

Si vas a migrar de Retrolambda

De manera similar a Jack, Retrolambda no es compatible con bibliotecas de terceros que utilicen funciones del lenguaje Java 8. Si tu proyecto está configurado para usar el complemento Retrolambda, entonces debes eliminar este último para que tu proyecto pueda volver a la cadena de herramientas predeterminada.

Abre tu archivo build.gradle a nivel de proyecto y elimina Retrolambda como dependencia del proyecto:

Luego, elimina el complemento Retrolambda de cada uno de tus archivos build.gradle a nivel de módulo:

Prueba tu compatibilidad con Java 8

La manera más sencilla de verificar que tu proyecto ahora sea compatible con Java 8 es escribir una expresión lambda rápida y ver si tu proyecto aún puede compilarse.

Agrega un botón a tu interfaz de usuario (o usa un botón que ya exista), y luego implementa un onClickListener para este botón utilizando una expresión lambda. No te preocupes si el siguiente código no tiene mucho sentido ahora, ¡lo tendrá al final de este artículo!

Test your lambda expression by triggering the Java 8 toastTest your lambda expression by triggering the Java 8 toastTest your lambda expression by triggering the Java 8 toast

Comprueba que tu proyecto aún pueda compilarse, ya sea seleccionando Sincronizar en el banner que aparece, o seleccionando Herramientas > Android > Sincronizar proyecto con archivos Gradle en la barra de herramientas de Android Studio.

Si Android Studio no muestra ningún error, entonces estás listo para comenzar a usar todas las funciones que enumeramos al principio de este artículo, ¡incluyendo las expresiones lambda!

¿Por qué son tan importantes las expresiones lambda?

Las expresiones lambda fueron sin duda la característica nueva más importante de Java 8, y pueden tener un enorme impacto en la cantidad de código repetitivo que necesitas escribir al crear casi cualquier aplicación Android.

Esencialmente, una expresión lambda representa a una función que no pertenece a ninguna clase, y que puedes enviar con facilidad y luego ejecutar a petición.

Esta característica se deshace de una frustración que muchos desarrolladores de Android han experimentado con Java durante mucho tiempo: como lenguaje orientado a objetos, pasar bloques de código siempre ha parecido más difícil de lo que debería ser. Por ejemplo, si quisieras crear un nuevo hilo y luego enviarle algo de código, normalmente tendrías que crear una instancia de un hilo con una implementación anónima de la interfaz Runnable, ¡lo cual es mucho trabajo solamente para pasar un poco de código! Al proporcionar una manera sencilla de enviar una función a un método, las expresiones lambda tienen el potencial de simplificar algunas de las tareas más comunes que deberás realizar como desarrollador de Android.

Las expresiones lambda también serán una adición bienvenida para cualquier desarrollador de Java que desee adoptar un enfoque más funcional para su programación. Antes de Java 8, la codificación en un estilo funcional inevitablemente requería que escribieras mucho código repetitivo, pero ahora que puedes enviar funciones usando expresiones lambda, escribir tu código Java de una manera menos orientada a objetos no tiene que implicar escribir una gran cantidad de clases anónimas.

¿Cómo puedo crear una expresión lambda?

Puedes crear una expresión lambda usando la sintaxis a continuación:

El operador de flecha se explica por sí mismo, pero las reglas sobre cómo debes estructurar el argumento y la expresión lambda pueden variar según lo que estés tratando de lograr, así que exploremos estos dos elementos con más detalle.

El argumento

El argumento es uno o más parámetros, que casi siempre están entre paréntesis. Incluso si tu expresión lambda no tiene ningún parámetro, aún así deberás proporcionar paréntesis vacíos, por ejemplo:

La excepción a esta regla es cuando tu método tiene un único parámetro con su tipo inferido, en cuyo caso puedes omitir los paréntesis:

Puedes utilizar varios parámetros en tu argumento separando cada parámetro con una coma:

Es posible inferir los tipos en las expresiones lambda, por lo que generalmente puedes omitir el tipo de dato de tu argumento. Sin embargo, si el compilador no puede inferir el tipo de dato, entonces deberás agregar el tipo delante de tus parámetros:

El cuerpo de la expresión

El cuerpo de la expresión es el código que quieres ejecutar, que puede ser una sola expresión o varias líneas de código. Si quieres ejecutar varias líneas, deberás crear un bloque de instrucciones rodeando esta sección de tu código con llaves:

Si tu expresión devuelve un valor, este debe devolverse con una instrucción return, por ejemplo:

Uso de las expresiones lambda en tus aplicaciones Android

Ahora que tenemos una perspectiva general sobre las diferentes maneras en las que puedes estructurar una expresión lambda, echemos un vistazo a algunos de los escenarios más comunes en los que puedes usar expresiones lambda durante tu trabajo de desarrollo con Android.

Expresiones lambda para el manejo de eventos

Una aplicación típica de Android tiene que ser capaz de responder a una amplia gama de eventos de entrada del usuario, y las expresiones lambda pueden permitir que este manejo de eventos sea mucho más sencillo.

En el siguiente código, estamos usando una clase anónima para crear una instancia de onClickListener con un método onClick sobrescrito. Lo más probable es que hayas escrito este tipo de código en innumerables ocasiones.

Al reescribir el código anterior con una expresión lambda, podemos eliminar todo lo siguiente:

  • la creación de la instancia de la clase: new View.OnClickListener()
  • el modificador de acceso, el nombre del método y el tipo: public void onClick(View view)
  • y los tipos de parámetros, para que no tengas que escribir View view

Esto significa que podemos implementar exactamente la misma funcionalidad utilizando una sola línea:

Expresiones lambda para la programación multihilo

La programación multihilo es otro escenario común en el que las expresiones lambda pueden ayudarte a escribir código más limpio. De forma predeterminada, Android tiene un único hilo de IU (interfaz de usuario) que es responsable de controlar toda la interacción del usuario, enviar eventos a los widgets de IU adecuados y modificar la interfaz de usuario. Tan pronto como bloquees este hilo de interfaz de usuario con cualquier operación intensiva o de larga duración, tu aplicación dejará de responder e incluso puede activar el cuadro de diálogo ANR (La aplicación no responde, o Application Not Responding en inglés) de Android. Por lo tanto, crear hilos adicionales y asignar código para que se ejecute en esos hilos es a menudo una parte esencial del desarrollo con Android.

Antes de Java 8, la asignación de código para que fuera ejecutado en un hilo adicional requería que crearas una clase anónima que implementara la interfaz Runnable:

Alternativamente, podías crear una instancia de un nuevo hilo con una implementación anónima de la interfaz Runnable:

Reemplazar esta clase anónima con una expresión lambda puede permitir que esta tarea, que se realiza con frecuencia, sea mucho más concisa:

Por último, si estás utilizando la biblioteca RxJava o RxAndroid, puedes usar expresiones lambda para ayudarte a crear observables.

Aquí estamos creando un Observable simple que emite la cadena "hello world" ("hola mundo") a todos sus Observers:

El uso de una expresión lambda te permite reemplazar todo ese código Action1 con una sola línea:

Uso de expresiones lambda en tu código real

Después de leer toda la teoría detrás de una nueva herramienta, el siguiente desafío es acostumbrarse a usarla de verdad. Esto puede ser particularmente difícil con algo como las expresiones lambda, que están diseñadas para ser utilizadas en lugar del familiar código repetitivo, ya que siempre existe la tentación de simplemente recurrir a lo que ya sabes.

Android Studio tiene algunas funciones que pueden ayudarte, dándote ese impulso final para reemplazar el código familiar pero anticuado con las nuevas y radiantes expresiones lambda.

La primera función es el menú de acciones de intención de Android Studio, que puede convertir automáticamente cualquier clase anónima compatible en la expresión lambda equivalente. Esto es perfecto si en alguna ocasión no estás seguro de cómo escribir un fragmento de código en particular en el formato de una expresión lambda: simplemente escríbelo como de costumbre, y luego use la función de conversión automática del menú de acciones de intención.

Para convertir automáticamente una clase anónima en una expresión lambda:

  • Coloca tu cursor sobre la clase anónima, y Android Studio debería mostrar un diálogo de información sobre la herramienta, indicándote que puede convertir esta sección de código en una expresión lambda.
  • Presiona las teclas Alt/Opción-Intro de tu Mac, o usa el acceso directo Alt-Intro si eres usuario de Windows o Linux.
  • Selecciona la opción Reemplazar con lambda en el menú contextual.

Select Replace with lambda from the context menu that appearsSelect Replace with lambda from the context menu that appearsSelect Replace with lambda from the context menu that appears

Alternativamente, puedes usar la herramienta Inspección de Android Studio para marcar todas las clases anónimas que pudieras reemplazar con una expresión lambda a lo largo de todo tu proyecto. A continuación, puedes volver a escribir cada clase anónima manualmente o dejar que la función de conversión automática de Android Studio te muestre cómo se hace.

Para resaltar todas las clases anónimas que Android Studio podría reemplazar con una expresión lambda:

  • Selecciona Analizar > Ejecutar inspección por nombre en la barra de herramientas de Android Studio.
  • En la ventana emergente que aparece, comienza a escribir El tipo anónimo puede reemplazarse con lambda y, a continuación, selecciona esta opción cuando aparezca en el menú desplegable.

Select Anonymous type can be replaced with lambda from the Enter inspection name popupSelect Anonymous type can be replaced with lambda from the Enter inspection name popupSelect Anonymous type can be replaced with lambda from the Enter inspection name popup

  • En la ventana siguiente, selecciona Todo el proyecto para marcar todas las clases anónimas a lo largo de tu proyecto. Alternativamente, puedes especificar módulos o archivos individuales en los que Android Studio deba ejecutar esta inspección.
  • Haz clic en OK.
  • Selecciona Analizar > Inspeccionar código en la barra de herramientas de Android Studio.

Ahora debería aparecer el panel Resultados de la inspección y debería mostrar una lista de todas las clases anónimas que puedes reemplazar con una expresión lambda. Para echar un vistazo más de cerca a una clase anónima, simplemente haz doble clic en esa clase en la ventana Resultados de la inspección y Android Studio abrirá el archivo y te llevará a la línea exacta que contiene esta clase anónima en particular.

Para reemplazar la clase anónima seleccionada actualmente con una expresión lambda, haz clic en el botón Reemplazar con lambda.

In the Inspection Results window select the Replace with lambda button In the Inspection Results window select the Replace with lambda button In the Inspection Results window select the Replace with lambda button

Si Android Studio no abre la ventana Resultados de la inspección automáticamente, puedes abrirla manualmente seleccionando Ver > Ventanas de herramientas > Resultados de la inspección en la barra de herramientas de Android Studio. Si Resultados de la inspección no aparece en el submenú Ventanas de herramientas, es posible que debas seleccionar primero Analizar > Inspeccionar código... desde la barra de herramientas de Android Studio.

Pruebas de expresiones lambda

A pesar de los muchos beneficios que las expresiones lambda tienen para ofrecer, hay un inconveniente importante que debes tener en cuenta antes de agregarlas a tu código. Dado que las expresiones lambda no tienen un nombre, no puedes llamarlas directamente desde tu código de prueba, por lo que agregar una gran cantidad de expresiones lambda al proyecto puede dificultar el proceso de pruebas.

Idealmente, tus expresiones lambda deberían ser muy simples de desglosar, por lo que no poder probarlas unitariamente no debería ser un problema demasiado grande. Sin embargo, si necesitas probar una expresión lambda, siempre puedes tratarla como un método privado y probar unitariamente el resultado, en lugar de la expresión lambda en sí. Alternativamente, puedes refactorizar la expresión lambda en su propio método, para que puedas hacer referencia a ella directamente y, por lo tanto, probarla como se hace normalmente.

Conclusión

En esta primera publicación sobre las características del lenguaje Java 8, analizamos cómo configurar tus proyectos de Android para que sean compatibles con Java 8, además de cómo reducir el código repetitivo reemplazando las clases anónimas con expresiones lambda.

En la siguiente publicación, te mostraré cómo recortar aún más código de tus proyectos Android combinando expresiones lambda con referencias a métodos, y cómo puedes mejorar tus interfaces con métodos de interfaz predeterminados y estáticos.

Mientras tanto, ¡echa un vistazo a algunas de nuestras otras publicaciones sobre el desarrollo de aplicaciones para Android!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.