· 4 min read Posted by Gustavo Fão Valvassori
Jetpack Compose to Compose Multiplatform: Transition Guide
Jetpack Compose is the current standard tool for building UI in Android applications. It’s a declarative UI toolkit that allows you to build your UI using Kotlin code. Like many other Android libraries, it is open-source and maintained by Google.
Just a couple of days after the first stable release of Jetpack Compose, JetBrains announced that they are working on a fork of Compose that is compatible with Kotlin Multiplatform. This means that you can use the same codebase to build your UI for Android, iOS, JVM, and the Web.
As you can imagine, this compilation change is not automatic, as the JetBrains version is a fork of the original Compose library. But in two steps, you can make your project compatible with multiple platforms.
Step 1: Migrating your module to KMP
The first step to use Compose Multiplatform, is to make your module compatible with Kotlin Multiplatform. This means
that you need to include the kotlin-multiplatform
plugin in your build.gradle.kts
file and configure the targets.
You can start with the Android target and add the other platforms later.
plugins {
id("com.android.application")
// or
id("com.android.library")
// Replace `kotlin("android")` with:
kotlin("multiplatform")
}
// Declare android target
kotlin {
androidTarget()
}
android {
// Your android app configuration
}
Now you need to create the commonMain
and the androidMain
source sets, and move your code to them. The code that
does not depend on Java or Android APIs can be directly moved to commonMain. The code that depends on Android APIs
should be moved to androidMain.
Last but not least, if your android
configuration has a compileOptions
block to define the Java version, you should
also update the androidTarget
declaration to use the same Java version.
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
}
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
Without it, you will get a compilation error similar to the one below:
Inconsistent JVM-target compatibility detected for tasks ‘compileDebugJavaWithJavac’ (1.8) and ‘compileDebugKotlinAndroid’ (17).
Step 2: Migration to Compose Multiplatform
Jetpack Compose is enabled by a “build feature” in your project. If you already have it set up, you probably already
have these few lines in your project build.gradle.kts
file:
android {
// Enabling Compose
buildFeatures {
compose = true
}
// Defining Compose version
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
}
}
Unlike Jetpack, the Compose Multiplatform is enabled through a plugin. So the first step to use it, is declaring
the plugin on you project root build.gradle.kts
file and removing Jetpack Compose configuration:
plugins {
kotlin("multiplatform") version "1.9.23" apply false
id("org.jetbrains.compose") version "1.6.1" apply false
}
And in your module build.gradle.kts
:
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
}
After that, all you need to do is include the Compose libraries in the common main source sets. To help you with this
challenge, the plugin provides a helper compose
variable with core Compose Multiplatform modules.
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.ui)
implementation(compose.animation)
}
}
}
Now your project is Multiplatform Ready and using Compose Multiplatform. If you want to build for other targets, all you
need to do is add them to your build.gradle.kts
file.
Bonus: Compose Resources
The 1.6.0 release of Compose Multiplatform has included support for resources. This means that you can now configure and use strings, images and other resources types in your common code.
To enable it, you must include the resources library to you common module, and create a new resource dir called
composeResources
.
kotlin {
sourceSets {
commonMain.dependencies {
implementation(compose.components.resources)
}
}
}
The current implementation is very similar to Android Resources, so it should be easy to migrate your current resources to the new format. Some of them can just be copied and paste to the common resource dir and it will work. Here is a list of supported resource types:
- Strings/String Array
- Drawable/Vector Images
- Fonts
- Files (similar to Android Raw resources)
Some types are not supported yet, but they may be added in future releases. Here is a list of unsupported resource types:
- Integers
- Booleans
- Colors
- Plurals
- Dimensions
To access it on your Kotlin code, all you need to do is Replace the R
class with the new Res
class. If you don’t see
the Res
class in your code, can trigger the generateComposeResClass
task.
Conclusion
Migrating projects from Jetpack Compose to Compose Multiplatform is a simple process that can be done in a few steps. The process will be even easier if your code has fewer couplings with Android-only APIs or platform libraries. And with the new resources support, most Android resources can be migrated to Compose Multiplatform without any changes.
If you need some examples on how this migration can be done, you can check the last commits from the Compose Animations project that was recently migrated to Compose Multiplatform.