Aunque ya lo comenté por encima en otro artículo, me gustaría explicar más en profundidad cómo funcionan las lambdas en Kotlin, y cómo estas transforman las interfaces con un sólo método en lambdas cuando estamos trabajando con librerías Java.
En particular te voy a mostrar algunos ejemplos sobre cómo simplifican la utilización del Framework de Android, y veremos el setOnClickListener
de las vistas de Android en detalle.
Si quieres aprender cuál es la situación de Kotlin en el mercado, por qué debes aprenderlo y los primeros pasos para que veas lo fácil que es, he preparado un training gratuito de hora y media al que puedes unirte haciendo click aquí
Transformación del setOnClickListener
Una de las funcionalidades que más me gustan de Kotlin es que simplifican mucho el trabajo con el framework de Android gracias a algunas convenciones.
Por ejemplo, la función setOnClickListener
, que en Java se define así:
public void setOnClickListener(OnClickListener l) { ... }
Cuando la utilizamos en Kotlin, su correspondiente es el siguiente:
fun setOnClickListener(l: (View) -> Unit)
Esto nos ahorra la necesidad de tener que crear una implementación anónima de la interfaz, simplificando mucho la UI.
Utilizando setOnclickListener. La forma original
Siguiendo lo anterior, ya nos ahorramos bastante código. Esto es lo que tendríamos si tuviéramos que crear una clase anónima de OnClickListener
:
view.setOnClickListener(object : View.OnClickListener { override fun onClick(v: View?) { toast("Hello") } })
Pero verás que el editor te muestra un warning directamente, y te recomienda usar la forma de la lambda.
Esta es la transformación que puedes hacer:
view.setOnClickListener({ v -> toast("Hello") })
Mucho más sencillo, ¿verdad? Pero aún se puede simplificar más
Si el último parámetro de una función es a su vez una función, esta puede ir fuera de los paréntesis
Por tanto, podemos extraer el listener de la siguiente forma:
view.setOnClickListener() { v -> toast("Hello") }
Si tuviéramos más parámetros, el resto de parámetros irían dentro de los paréntesis, incluso aunque estos fueran funciones. Sólo el último parámetro se puede extraer.
Si una función sólo tiene un parámetro, y este es una función, los paréntesis se pueden eliminar
Para tener unos paréntesis vacíos, mejor los eliminamos directamente
view.setOnClickListener { v -> toast("Hello") }
Esto viene genial para crear bloques de código. De esta forma podemos definir DSLs que modelen nuestro propio lenguaje.
Un ejemplo muy típico es el de la página de referencia de Kotlin, donde crean un DSL para crear HTML por código.
Si no se usan los parámetros de una lambda, se puede eliminar el lado izquierdo de la función
La vista (v
) no la estamos usando, así que nos la podemos cargar:
view.setOnClickListener { toast("Hello") }
Además, en las funciones que sólo reciben un parámetro, en vez de definir el lado izquierdo, podríamos utilizar la palabra reservada it
, ahorrándonos algunos caracteres.
Por ejemplo, si utilizáramos la vista para pasársela a otro método:
view.setOnClickListener { v -> doSomething(v) }
Tenemos la opción de usar simplemente it
:
view.setOnClickListener { doSomething(it) }
Las lambdas son tus amigas
Ya ves que la diferencia de código es bastante importante. Y no sólo por los caracteres que te ahorras (como un 70%) sino por lo que ayuda a la legibilidad.
En vez de tener que saltar todo el código que no aporta nada para encontrar lo útil, nos quedamos con lo que de verdad importa.
Anímate y vente a mí training gratuito, donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero. Descúbrelo todo sobre el lenguaje del futuro.
Y si la interfaz utiliza varias funciones?
Puedes, o bien pasar varias lambdas, o una interfaz que tenga todas. Aquí ya es cuestión de gustos, yo he visto ambas.
¿Y si la función que se llama recibe varios tipos de interfaz con una sola función? Por ejemplo para escuchar distintos tipos de eventos que vienen de distintas fuentes
Entonces por definición no es una función, sino varias. Una función siempre tiene los mismos tipos de entrada y de salida.