Lambdas en Kotlin, y cómo simplifican la tarea en Android (KDA 07)
Antonio Leiva

Las lambdas son una de las herramientas más potentes en Kotlin, y en cualquier otro lenguaje moderno, ya que permite modelar funciones de forma mucho más sencilla.

La única forma que tenemos de hacer esto en Java 6 es mediante la declaración de interfaces con un único método, y creando objetos anónimos que implemente esas interfaces.

Las lambdas, y sobre todo cómo las lambdas se definen en Kotlin, nos abren un mundo infinito de posibilidades. Iremos viendo algunos de esos casos en siguientes artículos.

Si quieres empezar hoy, te recomiendo que le eches un vistazo a mi training gratuito, donde tendrás una hora y media de contenido para saber cuáles son tus siguientes pasos a dar para convertirte en un experto en Kotlin.

Training Revienta tu productividad en Android con Kotlin

Lambdas en Kotlin

Una lambda es una forma de representar una función, y ya vimos un ejemplo de ello cuando explicábamos el setOnClickListener :

val view = findViewById(R.id.welcomeMessage)
view.setOnClickListener { v -> navigateWithView(v) }

Como ves, en el lado izquierdo se definen los valores de entrada de la función (en este caso una vista v), y en el lado derecho la operación que realiza dicha función.

Cómo definir una función que acepte lambdas

Si quisiéramos definir nosotros mismos esa función en lenguaje Kotlin, tendríamos lo siguiente:

fun setOnClickListener(listener: (view: View) -> Unit){}

Esto es lo que se conoce como una Higher-Order Function, o función de alto orden, porque es una función que recibe una función por parámetro, o que devuelve una función.

Transformación de apariencia

La forma natural de llamar a esta función sería la siguiente:

view.setOnClickListener({ v -> navigateWithView(v) })

Pero ya hemos visto que hay una forma más compacta de hacer esto, y que además nos ayudará a hacer cosas muy chulas que veremos justo después. ¿A qué se debe esto?

Esto es porque si el último parámetro de una función es a su vez una función, podemos sacarlo de los paréntesis:

view.setOnClickListener(){ v -> navigateWithView(v) }

Pero además, si sólo hay una función como parámetro, nos podemos cargar directamente los paréntesis

view.setOnClickListener { v -> navigateWithView(v) }

Creación de DSLs

Esto nos permite crearnos nuestros propios DSLs, que pueden llegar a crear mini-lenguajes. En la web de referencia de Kotlin hay un ejemplo con HTML, pero aquí vamos a poner uno más sencillo.

Imagina que quieres crear bloques de código que se ejecuten en otro hilo. Podrías tener una función que reciba a su vez la función que queremos ejecutar en segundo plano:

fun doAsync(f: () -> Unit) {
    Thread({ f() }).start()
}

Esta función crea un hilo con un Runnable que lo único que hace es ejecutar la función que se le pasa por parámetro. Como Runnable  es una clase con un único método en Java, se puede sustituir por una lambda. Luego ejecuta ese hilo.

Ahora en nuestro código podemos crear bloques asíncronos:

doAsync { 
    op1()
    op2()
    op3()
}

Todo lo que está entre los corchetes se ejecutará en un hilo secundario.

Funciones inline

Lo malo de crear funciones que reciban funciones, es que para ello el compilador necesita crearse clases anónimas. Pero esto se soluciona fácilmente añadiendo la palabra reservada inline.

Una función inline no consume tantos recursos, puesto que lo que se hará en tiempo de compilación es sustituir esa función por su código en los sitios donde se llame.

La función doAsync la podemos hacer inline:

inline fun doAsync(crossinline f: () -> Unit) {
    Thread({ f() }).start()
}

El crossinline en este caso es necesario porque se está llamando a f() desde otro contexto de ejecución (otra lambda). No te preocupes, porque el compilador te avisa cuando hace falta usarlo.

Conclusión

Como ves, con las lambdas podemos simplificar mucho nuestro código, e incluso conseguir cosas que antes eran impensables.

Además, la nomenclatura específica de Kotlin hace que podamos crear nuestro propio “lenguaje”, y crear bloques de código con sentido que hagan lo que necesitemos.

Si todo esto te apasiona tanto como a mí, te animo a que te apuntes a mi training gratuito donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero.

Quizá también te interese…

2 formas de recolectar Flows en la UI que SÍ funcionan

2 formas de recolectar Flows en la UI que SÍ funcionan

En la serie de artículos sobre Programación Reactiva con Flow hemos visto muchos conceptos, y hemos aprendido cómo aplicarlos al desarrollo Android. Pero hay algo que no hemos hecho del todo bien. Esto es la recolección de Flows desde la Activity (o el Fragment, en...

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

¡Vaya viaje por el que hemos pasado en estos artículos! Hace ya varios de ellos empezamos hablando sobre la programación reactiva con Flow, y hemos aprendido un montón de conceptos e ideas sobre cómo aplicarlos en el día a día. Pero nada de esto está completo si no...

Convertir cualquier callback en un Flow con CallbackFlow

Convertir cualquier callback en un Flow con CallbackFlow

Existen varios tipos de Flows muy particulares que nos van a solucionar la vida cuando tengamos que hacer cosas muy concretas. Ya vimos StateFlow en un artículo anterior, y en esta ocasión hablamos de CallbackFlow ¿Qué es CallbackFlow? Es un tipo de Flow que nos...