Following Google I/O 2024, Kotlin Multiplatform has established itself as one of the main alternatives for creating cross-platform applications for mobile devices, desktop, and web.
What is KMP?
Kotlin Multiplatform is a technology that allows developers to create cross-platform applications. Instead of writing separate code for each platform, it enables sharing a common codebase across different platforms such as Android, iOS, web, and more. This approach facilitates development, maintenance, and significantly reduces development time, all while using the Kotlin language.
KMP is developed by JetBrains. Unlike other cross-platform solutions, it does not aim to replace native tools but rather to complement them by sharing business logic, data models, and algorithms between platforms. Meanwhile, the user interface and other specific parts can be developed natively (or not).
How to create our first project in 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:
Let’s get to work! We are going to create our first project in KMP, and for that, we will use the installation wizard provided on the website:
https://kmp.jetbrains.com/
It will generate a project with all the necessary configuration to work with KMP.
It is worth noting that this wizard has a Templates tab that will allow us to create KMP projects starting from different scenarios, such as a shared UI project with Compose Multiplatform or a project with a native UI for each platform and shared business logic, among other examples.
To configure our KMP project from scratch, we will follow these steps:
1. Select a Project Name and an ID for it.
2.We will select which platforms we want to cover with our project. As we can see, we can work with:
- Android
- iOS
- Desktop
- Web (in alpha)
- Server
When we select iOS, it allows two implementations: with the native UI using SwiftUI or shared with Compose Multiplatform (Jetpack Compose).
The latter option is currently in Beta. However, it will be the one I use to configure the project for this article.
3. Once our project is configured, we click on download, and this generates a compressed file that we can open in Android Studio.
Scaffold and configuration of a KMP project
Project Scaffold
Once we have downloaded the project and opened it with Android Studio, we will take a look at the project scaffold to identify and locate the folders, packages, and modules that are worked on in a KMP project.
The first thing we will do is switch to the Project view, which will give us a complete view of the folders in our project.
Those of us who develop with Android will find the scaffold of a KMP project familiar, but there are some differences compared to a common Android project. We can see that we have a composeApp
module, and within it, androidMain
, commonMain
, and iosMain
.
Then, at the root level of composeApp
, we can see an iosApp
module.
Overview of each module:
- composeApp: This module is intended for the user interface using Jetpack Compose. It is where the visual part of the application is developed, leveraging the advantages of Compose to create reactive and declarative interfaces.
- androidMain: This module contains the platform-specific code for Android. Here, you can implement functionalities that are exclusive to Android.
- commonMain: This module includes the code shared across all platforms (Android and iOS, in our case). It defines business logic, data models, services, and any other functionality that does not depend on a specific platform. This is the heart of your KMP application, where all the code is shared between different platforms.
- iosMain: This module contains the platform-specific code for iOS. Like
androidMain
, it implements features and functionalities that are exclusive to iOS, using the tools and APIs provided by Apple. - iosApp: This module is used to configure the application on iOS. Here, you can define the app configuration, initialize the UI using Swift or SwiftUI, and handle any platform-specific interactions for iOS.
Gradle Configuration
If we look at the build.gradle.kts
file of the composeApp
module, we can see a configuration Gradle file. Let’s focus on a specific section.
In the sourceSets
, the dependencies to be included in the different sources are defined. In other words, in sourceSets
, we define the set of sources that our app will have. In a multiplatform project, it is common to have different sets of sources for different platforms (such as Android, iOS, or the common part shared between them).
In this case, androidMain.dependencies
contains the Android-specific code, and commonMain.dependencies
contains the code common to all platforms. If we had selected the project with a native UI in the Wizard, we would have the iOS dependency with its corresponding implementations.
Compose Multiplatform, a UI to rule them all
Compose Multiplatform is an extension of Jetpack Compose that allows creating user interfaces declaratively and reactively on multiple platforms (Android and iOS in our case). It leverages the power and versatility of Jetpack Compose to achieve results on various platforms with a single codebase.
When we talk about Compose Multiplatform, we are not only sharing business logic but also UI, making it very easy to create applications for different platforms with a single codebase. Next, we will see how we can easily create a list of items on both platforms with the same code.
Creating our shared UI
For this example, we will create a list of cities around the world, where we will show an image, name, country, and description. Let’s get started!
We create a data class City
for each item in our list.
Statically, we are going to create a list of cities around the world where we will load images added locally in commonMain > composeResources > drawable
.
For this, I have created an object CitiesUtils
that contains a list of cities.
Now we create a composable function to draw the item that will be displayed in the list of cities.
To finish, in the App
function, we load the static list of cities that we have in our CitiesUtils
object and iterate over it to draw a list of cities.
The final result of our view would be the following:
Running our application on emulators
To run our application on the Android emulator, we simply need to launch composeApp
on the emulator we have configured.
But to launch on the iOS emulator, we first need to install the Kotlin Multiplatform Mobile plugin for Android Studio, which allows launching the iOS emulator from the Android Studio options. Additionally, you must have the latest version of XCode installed on your Mac. Once the plugin is installed, we can select iosApp
and start it. The iOS emulator will open with our app.
And just like that, the magic happened! With a single codebase, we have both iOS and Android up and running.
Advantages and Disadvantages of KMP
In this article, we have seen how to create and configure our KMP project from scratch, and how, with Compose Multiplatform, to use the same UI for different platforms, all within the Kotlin language ecosystem. But what are the advantages and disadvantages of this technology?
Conclusions
In my opinion, KMP is making a strong impact in the cross-platform sector. The support from Google makes it the number one technology for tackling cross-platform development and ensures that the Kotlin language is not reserved only for Android developers. With KMP, the doors are opened to web, backend, mobile, and desktop development with a single language as the standard, none other than Kotlin.
If we add to this the interoperability of being able to use native UI or Compose Multiplatform for development, it makes KMP undoubtedly the best option at the moment.