Kotlin Multiplatform Development: Shared Code, expect/actual & Cross-Platform Targets
1. What is Kotlin Multiplatform Development?
Kotlin Multiplatform Development (KMP) allows developers to write shared Kotlin code that can be compiled for multiple platforms (e.g., Android, iOS, JVM, JavaScript, Native) from a single codebase. It promotes code reuse while allowing platform-specific implementations for unique requirements.
Key Benefits:
- Code Reuse: Share business logic, models, and utilities across platforms.
- Platform-Specific Code: Use
expect/actualdeclarations for platform differences. - Native Performance: Compiles to native binaries for each target.
- Interoperability: Works with Java, Swift, Objective-C, and JavaScript.
Use Case: Building a mobile app with shared logic for Android and iOS, or a web app with desktop and browser targets.
Target Platforms:
- JVM: For server-side (e.g., Spring Boot) or Android apps.
- Android: Native Android development with Kotlin.
- iOS: Compiles to Swift/Objective-C frameworks for iOS/macOS.
- JavaScript: Compiles to JavaScript for web or Node.js.
- Native: Compiles to native binaries for desktop, embedded systems, or iOS.
- Common: Shared code that compiles to all targets.
2. How do you set up a Kotlin Multiplatform project?
Tools: Use IntelliJ IDEA (Community or Ultimate) or Android Studio with the Kotlin Multiplatform plugin.
Steps:
- Create a new project:
File > New > Project > Kotlin Multiplatform. - Configure targets (e.g., JVM, Android, iOS, JS).
- Define
build.gradle.ktswith shared and platform-specific sources. - Use
expect/actualfor platform-specific implementations.
Project Structure:
src/
├── commonMain/kotlin/ # Shared code
├── jvmMain/kotlin/ # JVM-specific code
├── androidMain/kotlin/ # Android-specific code
└── iosMain/kotlin/ # iOS-specific code
3. Can you give an example of a basic Kotlin Multiplatform setup?
// build.gradle.kts
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose") version "1.5.4" // For UI if needed
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "1.8"
}
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js(IR) {
browser {
commonWebpackConfig {
cssSupport {
enabled.set(true)
}
}
}
binaries.executable()
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
}
// src/commonMain/kotlin/Employee.kt
// Shared code
expect class Employee(name: String, salary: Double)
fun calculateBonus(salary: Double, years: Int): Double {
return if (years >= 5) salary * 0.1 else salary * 0.05
}
// src/jvmMain/kotlin/Employee.kt
// JVM-specific implementation
actual class Employee actual constructor(actual val name: String, actual val salary: Double) {
actual fun describe(): String = "Employee: $name, Salary: $salary"
}
// src/jsMain/kotlin/Employee.kt
// JavaScript-specific implementation
actual class Employee actual constructor(actual val name: String, actual val salary: Double) {
actual fun describe(): String = "Employee: $name, Salary: $salary (JS)"
}
Note:
build.gradle.ktsconfigures JVM and JS targets.commonMaincontains shared code withexpectdeclarations.jvmMainandjsMainprovideactualimplementations.- Run with
./gradlew runor in IntelliJ.
4. What are expect/actual declarations in Kotlin Multiplatform?
expect: Declares an expected declaration in commonMain, defining an interface that must be implemented per platform.
actual: Provides platform-specific implementations in source sets like jvmMain, androidMain, iosMain.
Use Case: Abstracting platform differences (e.g., date formatting on JVM vs. iOS).
5. Can you give an example of expect/actual?
// src/commonMain/kotlin/Platform.kt
expect fun getPlatformName(): String
// src/jvmMain/kotlin/Platform.kt
actual fun getPlatformName(): String = "JVM"
// src/jsMain/kotlin/Platform.kt
actual fun getPlatformName(): String = "JavaScript"
// src/commonMain/kotlin/Main.kt
fun main() {
println("Running on: ${getPlatformName()}")
}
Output (JVM):
Running on: JVM
Output (JS):
Running on: JavaScript
Note:
expectin common code;actualimplementations per platform.maincalls the platform-specific function.
6. What are common mistakes in Kotlin Multiplatform Development?
Setup:
- Incorrect
build.gradle.ktsconfiguration, causing build errors. - Missing
actualimplementations, leading to compilation failures.
expect/actual:
- Mismatching signatures between
expectandactual, causing errors. - Overusing
expect/actualfor simple shared code.
Platform-Specific Code:
- Not handling platform differences (e.g., iOS threading vs. Android).
- Including unnecessary platform-specific dependencies.
General:
- Not testing on all targets, missing platform bugs.
- Ignoring build times for large multiplatform projects.
7. What are best practices for Kotlin Multiplatform Development?
Setup:
- Use IntelliJ IDEA or Android Studio with KMP plugins.
- Start with common targets (JVM, Android, iOS); add JS/Native as needed.
expect/actual:
- Use for platform-specific APIs (e.g., networking, file I/O).
- Keep
expectsignatures simple and matchactualexactly.
Shared Code:
- Maximize shared logic in
commonMain. - Use platform-specific code only for unique requirements.
General:
- Test on all targets (e.g., unit tests in
commonTest). - Use Compose Multiplatform for UI sharing.
- Profile build times; use caching for faster compilation.
- Document platform-specific behaviors.