A raíz de la Google IO de 2024, Kotlin Multiplatform se ha asentado como una de las principales alternativas a la hora de crear aplicaciones multiplataformas para dispositivos móviles, escritorio y web.
¿Qué es KMP?
Kotlin Multiplatform es una tecnología que permite a los desarrolladores crear aplicaciones multiplataforma. En lugar de escribir código separado para cada una, permite compartir una base de código común entre diferentes plataformas, como Android, iOS, web y más, facilitando el desarrollo, el mantenimiento y reduciendo significativamente el tiempo de desarrollo, y todo esto bajo el lenguaje Kotlin.
KMP está desarrollado por Jetbrains, a diferencia de otras soluciones multiplataforma, no busca reemplazar las herramientas nativas, sino complementarlas al compartir lógica de negocio, modelos de datos y algoritmos entre ellas, mientras que la interfaz de usuario y otras partes específicas se pueden desarrollar de manera nativa (o no).
¿Cómo crear nuestro primer proyecto en KMP?
¡Pues manos a la obra!, vamos a crear nuestro primer proyecto en KMP y para ello vamos a utilizar el wizard de instalación que nos proveen desde la web:
Nos generará un proyecto con toda la configuración necesaria para trabajar con KMP.
Cabe destacar que este wizard tiene una pestaña de Templates que nos permitirá crear proyectos de KMP partiendo de diferentes escenarios, como por ejemplo un proyecto de UI compartida con Compose Multiplatform o un proyecto de UI nativa para cada plataforma y lógica de negocio compartida, entre otros ejemplos.
Para configurar nuestro proyecto en KMP desde cero, seguiremos los siguientes pasos:
1. Seleccionaremos un Nombre de proyecto y una ID para el mismo.
2. Seleccionaremos qué plataformas queremos abarcar con nuestro proyecto. Como podemos observar podemos trabajar con:
- Android
- IOS
- Escritorio
- Web (En alpha)
- Servidor
Si nos fijamos cuando seleccionamos iOS nos permite dos implementaciones con la UI nativa con SwitftUI o compartida con Compose Multiplatform (Jetpack Compose)
Esta última opción, hoy en día, está en Beta. No obstante, será con la que configure el proyecto para este artículo.
3. Una vez configurado nuestro proyecto pulsamos en descargar, y esto nos genera un archivo comprimido que podremos abrir desde Android Studio.
Scaffold y configuración de un proyecto KMP
Scaffold de proyecto
Una vez tenemos el proyecto descargado y lo hemos abierto con nuestro Android Studio vamos a echar un vistazo al scaffold de proyecto, para identificar y localizar las carpetas, paquetes y módulos sobre las que se trabajan en un proyecto KMP.
Lo primero que haremos es situarnos en una vista Project, que nos dará una vista completa de las carpetas de nuestro proyecto.
Quienes desarrollamos con Android nos sonará el Scaffold de un proyecto KMP, pero hay algunas diferencias con un proyecto Android común. Podemos ver que tenemos un módulo composeApp y dentro de él androidMain, commonMain e iosMain.
Luego a la altura de la raíz de composeApp podemos ver un módulo iosApp.
A grandes rasgos, cada uno de estos módulos serían:
- composeApp: Este módulo está destinado a la interfaz de usuario utilizando Jetpack Compose, es donde se desarrolla la parte visual de la aplicación, aprovechando las ventajas de Compose para crear interfaces reactivas y declarativas.
- androidMain: Este módulo contiene el código específico para la plataforma Android. Aquí puedes implementar funcionalidades que son exclusivas de Android.
- commonMain: Este módulo incluye el código compartido entre todas las plataformas (Android e iOS, en nuestro caso). Aquí se define lógica de negocio, modelos de datos, servicios, y cualquier otra funcionalidad que no dependa de la plataforma específica. Este es el corazón de tu aplicación KMP, donde se comparte todo el código entre las diferentes plataformas.
- iosMain: Este módulo contiene el código específico para la plataforma iOS. Al igual que androidMain, aquí implementan características y funcionalidades que son exclusivas de iOS, utilizando las herramientas y APIs que Apple ofrece.
- iosApp: Este módulo se utiliza para configurar la aplicación en iOS. Aquí se puede definir la configuración de la aplicación, inicializar la UI utilizando Swift o SwiftUI y manejar cualquier interacción específica de la plataforma iOS.
Configuración de gradle
Si nos situamos en el build.gradle.kts del módulo composeApp podemos ver un archivo gradle de configuración, pero vamos a detenernos en una sección en concreta.
En el sourceSets se definen las dependencias que se van a incluir en las diferentes fuentes. Es decir, en sourceSets definiremos el conjunto de fuentes que tendrá nuestra app. En un proyecto multiplataforma, es común tener diferentes conjuntos de fuentes para diferentes plataformas (como Android, iOS, o la parte común que se comparte entre ellas).
En este caso androidMain.dependecies contiene el código específico de Android, y commonMain.dependencies el que es común a todas las plataformas. En el caso de que hubiéramos seleccionado en el Wizard en proyecto con UI nativa, tendríamos la dependencia de ios con sus correspondientes implementaciones.
Compose Multiplatform, una UI para dominarlos a todos
Compose Multiplatform es una extensión de Jetpack Compose que permite crear interfaces de usuario de manera declarativa y reactiva en múltiples plataformas (Android e iOS en nuestro caso) Se sirve de la potencia y versatilidad de Jetpack Compose para con un unico código poder obtener resultados en varias plataformas.
Cuando hablamos de Compose Multiplatform ya no solo estamos compartiendo logica de negocio, también UI, lo cual hace muy sencillo crear aplicaciones para diferentes plataformas con un único código. A continuación, vamos a ver cómo de forma muy sencilla podemos crear una lista de ítems en ambas plataformas con un mismo código.
Creando nuestra UI compartida.
Para este ejemplo vamos a crear una lista de ciudades del mundo, donde mostremos una imagen, nombre, país y descripción. ¡Comencemos!
Creamos una data class City para cada elemento de nuestra lista.
De forma estática, vamos a crear una lista con ciudades del mundo donde cargaremos imágenes agregadas de forma local en commonMain > composeResources > drawable.
Para ello he creado un object CitiesUtils que contiene una lista de ciudades.
Ahora creamos una función composable para dibujar el ítem que se mostrará en la lista de ciudades
Para finalizar, en la función App cargamos la lista estática de ciudades que tenemos en nuestro objeto CitiesUtils, e iteramos sobre ella para dibujar una lista de ciudades
El resultado final de nuestra vista sería el siguiente:
Ejecutar nuestra aplicación en los emuladores
Para ejecutar nuestra aplicación en el emulador de Android no tenemos más que lanzar composeApp en nuestro emulador que tengamos configurado.
Pero para lanzar en el emulador de iOS primero debemos de instalar el plugins de Android Studio, Kotlin Multiplatform Mobile, que permite lanzar el emulador de iOS desde las opciones de Android Studio. Además, deberás de tener instalada la última versión de XCode en tu Mac. Una vez instalado el plugins, podemos seleccionar iosApp y arrancar. Se abrirá el emulador de iOS con nuestra app.
¡Y se hizo la magia! con un único código, tenemos funcionando iOS y Android.
Ventajas y desventajas de KMP
En este artículo hemos visto cómo crear y configurar nuestro proyecto KMP desde cero, y como, con Compose Multiplatform, usar una misma UI para diferentes plataformas y todo ello bajo el ecosistema del lenguaje Kotlin, pero ¿qué ventajas y desventajas tiene esta tecnología?
Conclusiones
En mi opinión KMP viene pisando fuerte en el sector de la multiplataforma, el apoyo de Google la convierte en la tecnología número uno para afrontar desarrollos multiplataforma y hace que el lenguaje Kotlin no se quede reservado solo para los desarrolladores Android. Con KMP se abren las puertas al desarrollo web, backend, mobile y desktop con un único lenguaje como bandera, ni más ni menos que Kotlin.
Si sumamos a esto la interpolaridad de poder usar la UI nativa o Compose Multiplatform para el desarrollo de estas, hacen que KMP sea sin duda la mejor opción del momento.