Kotlin多平台KMP实战:用Compose构建跨平台应用的5个核心模式
编程语言
Kotlin多平台:一套代码,全平台运行
iOS用Swift、Android用Kotlin、Web用TypeScript——跨平台开发成本居高不下。Kotlin Multiplatform(KMP)让你用同一套Kotlin代码共享业务逻辑,Compose Multiplatform共享UI,一次编写即可运行在Android、iOS、Desktop和Web上。2026年,KMP已成为跨平台开发的最优解之一。
本文将从5种核心模式出发,带你完成expect/actual机制→共享业务逻辑→Compose UI→平台API→生产构建的全链路实战。
核心概念
| 概念 | 说明 |
|---|---|
| KMP | Kotlin Multiplatform Platform,Kotlin跨平台方案 |
| expect/actual | KMP平台差异声明与实现机制 |
| Compose Multiplatform | 基于Jetpack Compose的跨平台UI框架 |
| 共享逻辑 | 多平台共用的业务逻辑代码 |
| 平台特定 | 针对特定平台的实现代码 |
| Kotlin/Native | 编译为原生二进制的Kotlin后端 |
| Kotlin/JS | 编译为JavaScript的Kotlin后端 |
| 互操作 | 与平台原生代码(Swift/JS/C)的交互 |
问题分析:KMP的5大挑战
- expect/actual理解成本:声明与实现分离的模式需要适应
- Compose Multiplatform成熟度:iOS端仍在Beta阶段
- 平台差异处理:iOS/Android/桌面API差异大
- 调试体验差:跨平台调试链路复杂
- 构建配置复杂:Gradle多平台配置学习曲线陡
分步实操:5种KMP实现模式
模式1:KMP项目结构与expect/actual
// commonMain/src/commonMain/kotlin/Platform.kt
expect class Platform() {
val name: String
}
fun getPlatform(): Platform {
return Platform()
}
// androidMain/src/androidMain/kotlin/Platform.kt
actual class Platform actual constructor() {
actual val name: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}
// iosMain/src/iosMain/kotlin/Platform.kt
actual class Platform actual constructor() {
actual val name: String = "iOS ${platform.Foundation.NSProcessInfo.processInfo.operatingSystemVersionString}"
}
模式2:共享业务逻辑层
// commonMain
class GreetingRepository {
private val platform = getPlatform()
fun greet(): String {
return "Hello from ${platform.name}!"
}
}
class UserViewModel {
private val repository = GreetingRepository()
private val _greeting = MutableStateFlow("")
val greeting: StateFlow<String> = _greeting.asStateFlow()
fun loadGreeting() {
_greeting.value = repository.greet()
}
}
模式3:Compose Multiplatform UI
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun App() {
var greeting by remember { mutableStateOf("Loading...") }
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = greeting,
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { greeting = GreetingRepository().greet() }) {
Text("Load Greeting")
}
}
}
}
}
}
模式4:平台特定API调用
// commonMain
expect class DateTimeFormatter() {
fun format(timestamp: Long): String
}
// androidMain
actual class DateTimeFormatter actual constructor() {
private val sdf = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
actual fun format(timestamp: Long): String = sdf.format(Date(timestamp))
}
// iosMain
actual class DateTimeFormatter actual constructor() {
actual fun format(timestamp: Long): String {
val date = NSDate(timeIntervalSince1970 = timestamp / 1000.0)
val formatter = NSDateFormatter().apply {
dateFormat = "yyyy-MM-dd HH:mm:ss"
}
return formatter.stringFromDate(date)
}
}
模式5:生产构建与发布
// build.gradle.kts
kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
jvm("desktop")
js(IR) {
browser()
}
sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
}
androidMain.dependencies {
implementation("androidx.activity:activity-compose:1.9.0")
}
}
}
避坑指南
坑1:commonMain引用平台特定API
// ❌ 错误:commonMain直接使用Android API
fun getPath() = android.os.Environment.getDataDirectory().path
// ✅ 正确:通过expect/actual声明
// commonMain
expect fun getDataPath(): String
// androidMain
actual fun getDataPath() = android.os.Environment.getDataDirectory().path
坑2:Compose iOS内存泄漏
// ❌ 错误:未释放iOS原生引用
class IOSBridge {
val delegate = object : NSURLSessionDelegate() { ... }
}
// ✅ 正确:使用WeakReference或手动释放
class IOSBridge {
private var delegateRef: WeakReference<NSURLSessionDelegate>? = null
fun cleanup() { delegateRef = null }
}
坑3:Kotlin/Native并发限制
// ❌ 错误:跨线程共享可变状态
var counter = 0 // 不同线程访问会崩溃
// ✅ 正确:使用AtomicReference
val counter = AtomicReference(0)
坑4:Gradle配置过于复杂
// ❌ 错误:所有配置写在一个build.gradle.kts
// 300+行的Gradle文件
// ✅ 正确:使用convention plugins拆分
// build-logic/convention/src/main/kotlin/KmpConventionPlugin.kt
class KmpConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.kotlin { /* 标准KMP配置 */ }
}
}
坑5:未处理平台字体差异
// ❌ 错误:使用平台特定字体名
Text(fontFamily = FontFamily("SF Pro"))
// ✅ 正确:使用Compose内置字体或条件判断
val fontFamily = if (Platform.isIOS) FontFamily("SF Pro") else FontFamily("Roboto")
报错排查
| 序号 | 报错信息 | 原因 | 解决方法 |
|---|---|---|---|
| 1 | Unresolved reference: expect |
未启用KMP插件 | 添加kotlin("multiplatform")插件 |
| 2 | Actual class has no corresponding expect |
expect/actual不匹配 | 检查commonMain和平台Main的声明 |
| 3 | Linker error iOS |
Kotlin/Native与C互操作问题 | 检查cinterop配置和.def文件 |
| 4 | Compose compiler error |
Compose版本不兼容 | 统一compose插件和compiler版本 |
| 5 | Gradle sync failed |
多平台依赖冲突 | 使用version catalog统一版本 |
| 6 | JS compilation error |
Kotlin/JS不支持反射 | 避免在commonMain使用反射API |
| 7 | iOS build timeout |
Kotlin/Native编译慢 | 启用增量编译和缓存 |
| 8 | ClassNotFoundException desktop |
JVM模块未正确配置 | 检查jvm()目标和mainClass |
| 9 | Module not found |
sourceSets路径错误 | 确认src/commonMain/kotlin目录结构 |
| 10 | SDK not found |
iOS SDK未安装 | 安装Xcode和Command Line Tools |
对比分析
| 维度 | KMP | Flutter | React Native | .NET MAUI |
|---|---|---|---|---|
| 语言 | Kotlin | Dart | JavaScript/TS | C# |
| UI共享 | Compose | Widget | JSX | XAML |
| 原生性能 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| 生态丰富度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| 学习曲线 | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 原生互操作 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| iOS成熟度 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
总结:Kotlin Multiplatform凭借expect/actual机制和Compose Multiplatform,在跨平台开发中提供了独特的灵活性。KMP适合已有Kotlin/Android生态的团队,可以渐进式共享代码而非全量重写。2026年Compose Multiplatform iOS端日趋成熟,KMP正成为跨平台开发的务实之选。
在线工具推荐
- JSON格式化:/zh-CN/json/format
- Hash计算:/zh-CN/encode/hash
- cURL转代码:/zh-CN/dev/curl-to-code
本站提供浏览器本地工具,免注册即可试用 →
#Kotlin多平台#KMP#跨平台开发#Compose Multiplatform#2026#编程语言