A Developerās Roadmap to Mastering Kotlin Multiplatform
A Developerās Roadmap to Mastering Kotlin Multiplatform ź“ė Ø
In modern mobile development, cross-platform frameworks are gaining popularity because they offer key advantages, such as reducing the resources needed to develop separate native apps and maintaining code consistency across different platforms.
By allowing developers to write shareable code, these frameworks enable faster development and easier maintenance, making them attractive not only to startups and large companies but also to individual developers. With a single codebase, itās possible to build multiple platform-specific apps, making cross-platform solutions highly efficient for both time and cost management.
Kotlin Multiplatform (KMP)Ā is another rising star in cross-platform development driven by the collaboration betweenĀ JetBrainsĀ and Google. It allows developers to share business logic seamlessly across multiple platforms, including Android, iOS, Desktop, and Web, all while using Kotlin. Compared to other cross-platform solutions likeĀ React NativeĀ orĀ Flutter, Kotlin Multiplatform offers performance that is closer to native, making it an attractive choice for developers seeking efficiency and native-like performance without sacrificing the benefits of cross-platform development.
In this article, youāll explore the Kotlin Multiplatform (KMP) ecosystem using theĀ Kotlin Multiplatform Developer Roadmap (skydoves/kmp-developer-roadmap
)Ā as your guide. The roadmap is designed to offer a comprehensive overview of the current KMP ecosystem, which provides suggested learning paths to help you better understand the various concepts involved in KMP development.
Kotlin Multiplatform Architecture
Kotlin Multiplatform doesnāt inherently provide a UI framework. Instead, it focuses on sharing business logic across multiple platforms while enabling developers to create platform-specific UIs for Android, iOS, and other targets. The core idea is to write common logic in Kotlin once and reuse it across platforms like Android, JVM, iOS, macOS, JavaScript, and Linux, while maintaining full control over each platformās native UI. This approach provides flexibility, as demonstrated in the illustration below:
Letās jump into the architecture with some code exploration! Before setting up your first Kotlin Multiplatform (KMP) project, ensure the following prerequisites:
- Install theĀ Kotlin Multiplatform PluginĀ in Android Studio.
- Launch Xcode at least once and accept the terms of use if you plan to build iOS apps.
After meeting these requirements, open theĀ Kotlin Multiplatform Wizard. This will generate a project structure similar to the one below, giving you a foundation for cross-platform development.
After selecting Android, iOS, and Web, the Kotlin Multiplatform Wizard downloads a project pre-configured with a multiplatform architecture. You can then open theĀ composeApp
Ā moduleāsĀ build.gradle.kts
Ā file to view the platform setup. This file outlines each targeted platformās configuration, dependencies, and shared code structure, helping you better understand the cross-platform architecture and how shared business logic integrates with platform-specific code below:
kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
moduleName = "composeApp"
browser {
val rootDirPath = project.rootDir.path
val projectDirPath = project.projectDir.path
commonWebpackConfig {
outputFileName = "composeApp.js"
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
static = (static ?: mutableListOf()).apply {
// Serve sources to debug inside browser
add(rootDirPath)
add(projectDirPath)
}
}
}
}
binaries.executable()
}
androidTarget {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}
}
In the code above, you can configure target platforms and create hierarchical structures by grouping similar platforms, likeĀ iosX64
Ā andĀ iosArm64
. This setup allows you to share common code between similar platform targets, simplifying maintenance and reducing redundancy.
You can set up the targets below to configure KMP project platform architecture:
applyDefaultHierarchyTemplate()
: Configures a default shared source set hierarchy, simplifying setup by establishing common dependencies and configurations across platform targets, like Android, iOS, and JVM. It enables code reuse by creating shared source sets with logical hierarchies.androidTarget()
: Adds Android as a target platform, allowing the KMP project to compile Android-specific code. For library modules,ĀpublishLibraryVariants("release")
Ā can be used to specify which build variants are published.iosX64()
,ĀiosArm64()
,ĀiosSimulatorArm64()
: Configures targets for different iOS CPU architectures, supporting iOS on x64 (for simulator), arm64 (for devices), and Simulator Arm64. TheĀbaseName
Ā field can specify a framework name, like āComposeApp,ā for the output.macosX64()
,ĀmacosArm64()
: Targets for macOS, allowing the code to be compiled for macOS on both x64 (Intel) and Arm64 (Apple Silicon) architectures. This setup supports building shared code for macOS applications.jvm()
: Compiles the shared code for the Java Virtual Machine (JVM), which is compatible with desktop and Android applications, providing easy integration with Java libraries and environments.wasmJs()
: Configures the project to target WebAssembly with JavaScript interop, enabling shared Kotlin code to execute as WebAssembly (WASM) in a web environment. This is especially useful for creating performant web apps.linuxX64()
,ĀlinuxArm64()
: Targets for Linux on x64 and Arm64 architectures, allowing the shared code to run on Linux environments, which is helpful for server-side applications or embedded Linux devices.
Each target broadens the reach of your KMP project by allowing the core business logic to run across different operating systems and architectures. This flexibility helps maximize code reuse while supporting the specifics of each platformās native capabilities.
If youāre ready to dive into building your first Android and iOS mobile applications with Kotlin Multiplatform, check out this guide:Ā Build Your First Android and iOS Mobile App With Kotlin Multiplatform.
Share Code
Kotlin Multiplatform lets you define a common interface specification across multiple platforms, unifying the interface hierarchy while allowing platform-specific implementations. To achieve this, you can useĀ expected
Ā andĀ actual
Ā declarations, which enable access to platform-specific APIs from Kotlin Multiplatform modules. This approach allows you to maintain platform-agnostic APIs in the common code, simplifying cross-platform development.
TheĀ expect
Ā keyword is used in the shared (common) code to declare a function, class, or property without defining its implementation. This acts as a placeholder, allowing you to specify the API that platform-specific modules will need to implement. For example, if you want to declare a shared function that logs across different platforms, you can declare a function calledĀ log
Ā like the code below:
// In common module
expect fun log(message: String)
TheĀ actual
Ā keyword is used in platform-specific modules to provide the implementation of theĀ expect
Ā declarations. For each platform (e.g., Android, iOS), you create theĀ actual
Ā implementation of the expected functionality. For instance, if you want to provide the actual implementation for the expectedĀ log
Ā function, you can define it differently for each specific platform, as shown in the example below:
// In Android module
actual fun log(message: String) {
Log.d("TAG", message)
}
// In iOS module
actual fun log(message: String) {
NSLog(message)
}
Now, you can use theĀ log
Ā function across the common module. This approach provides flexibility by allowing platform-specific code without altering the common code. Additionally, it enables you to maintain platform-independent logic in the common module, maximizing code reuse. For more information about theĀ expect
Ā andĀ actual
Ā declarations, check outĀ Expected and actual declarations.
Compose Multiplatform
Youāve discovered that Kotlin Multiplatform is designed to share business logic across platforms but doesnāt include any UI solutions by default. This can be confusing, as most cross-platform frameworks provide UI components or layers that enable building screens with a unified codebase across different platforms.
A great solution for cross-platform UI in Kotlin Multiplatform isĀ Compose Multiplatform, which builds on Kotlin Multiplatform and enables developers to share UI code written inĀ Jetpack ComposeĀ across various platforms. JetBrains has forked the Jetpack Compose library (for Android) into theĀ JetBrains/compose-multiplatform
Ā repository and created compatible Compose UI clients for multiple platforms, including iOS, Desktop, and WebAssembly (WASM).
With Compose Multiplatform, you can develop both Android and iOS applications using a unified UI implementation while sharing business logic written in Kotlin. Currently, Android and Desktop (Windows, macOS, Linux) support is stable, iOS is in beta, and Web is in alpha. For more details on future plans, check out theĀ Kotlin Multiplatform Development Roadmap for 2025.
AndroidX Library Compatibility
If youāre an Android developer, you might be wondering about the best ways to minimize migration costs from native Android to Kotlin Multiplatform, and that must be using the same tech stacks as much as possible, such as Jetpack libraries. The Android team is aware of this and has begun officially supporting KMP for several Jetpack libraries, as listed below:
- Lifecycle: Lifecycle-aware components that react to changes in the lifecycle state of other components.
- Room Database: A persistence library that provides an abstraction layer over SQLite, enabling robust database access with the full power of SQLite.
- DataStore: Enables asynchronous, consistent, and transactional data storage, addressing limitations of SharedPreferences.
- Paging: Facilitates gradual and efficient data loading.
- Annotation: Provides metadata to enhance code understanding for tools and developers.
- Collection: Optimizes memory usage for small collections.
Jetpack library releases for Android and iOS meet strict quality and compatibility standards. As Jetpack expands its Kotlin Multiplatform (KMP) support to other platforms, however, tooling and infrastructure are still developing. Check out theĀ sample project on GitHub (android/kotlin-multiplatform-samples
)Ā for KMP-supported Jetpack libraries.
According to theĀ official documentation, Jetpack libraries categorize platform support into three tiers:
- Tier 1: Android, JVM, iOS
- Tier 2: macOS, Linux
- Tier 3: watchOS, tvOS, Windows, WASM
For additional information on Kotlin Multiplatform support for Jetpack libraries, refer to theĀ Kotlin Multiplatform Overview.
Asynchronous
Asynchronous solutions are essential in mobile development due to limited resources compared to desktops. Both Android and iOS use the main thread (or UI thread) to handle all UI-related tasks, such as rendering elements, dispatching events, and managing interactions within the user interface.
For I/O or computationally intensive tasks like network requests or database queries, itās best to offload them to a worker thread. This keeps the main thread free for rendering and user interactions, ensuring a responsive UI. In Kotlin,Ā CoroutinesĀ provide a powerful asynchronous solution, supported at the language level and enhanced through libraries, making it ideal for efficient concurrency.
Coroutines fully support Kotlin Multiplatform, allowing you to use them seamlessly across multiple platforms. They offer a lightweight concurrency solution with robust error-handling APIs, providing greater flexibility than traditional threads. This makes Coroutines one of the most promising asynchronous solutions for Kotlin Multiplatform development.
If youāre an avidĀ ReactiveXĀ user, consider exploringĀ Reaktive on GitHub (badoo/Reaktive
), which brings ReactiveX extensions to Kotlin Multiplatform.
Network
On Android, Retrofit and OkHttp are the go-to solutions for handling type-safe HTTP network requests, streaming, and more. However, they donāt support Kotlin Multiplatform. Instead, there is another excellent HTTP asynchronous libraryĀ r, designed for creating multiplatform microservices and HTTP clients. Ktor is lightweight, flexible, and fully compatible with Coroutines, making them ideal for Kotlin Multiplatform projects.
Ktor is an asynchronous framework created by JetBrains for building applications and microservices in Kotlin. It supports both client-side and server-side development, making it versatile for building HTTP clients, REST APIs, web applications, and microservices across multiple platforms, including Android, JVM, JavaScript, and iOS. The key features of Ktor are:
- Asynchronous by Design: Built with coroutines in mind, Ktor is fully asynchronous, leveraging Kotlinās coroutines to provide high concurrency with minimal overhead.
- Multiplatform Support: Ktor can be used in Kotlin Multiplatform projects, allowing you to write HTTP clients that work across different platforms (Android, iOS, JVM, etc.) with the same codebase.
- Extensible and Modular: Ktor is modular, allowing you to add only the features you need, such as authentication, serialization, WebSocket support, and more, by including individual dependencies.
- Flexible Routing: Ktorās routing system is flexible, supporting path parameters, query parameters, and more. It enables organized API endpoints in server applications.
- Built-In Serialization: Ktor integrates with Kotlinās serialization library, making it easy to handle JSON, XML, and other serialization formats.
On the other hand, a solution calledĀ Foso/Ktorfit
Ā is built on top of Ktor. Ktorfit is an HTTP client and Kotlin Symbol Processor designed for Kotlin Multiplatform, inspired by Retrofit. It offers a similar interface-based approach to define HTTP request methods, making it familiar for those who have used Retrofit.