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大挑战

  1. expect/actual理解成本:声明与实现分离的模式需要适应
  2. Compose Multiplatform成熟度:iOS端仍在Beta阶段
  3. 平台差异处理:iOS/Android/桌面API差异大
  4. 调试体验差:跨平台调试链路复杂
  5. 构建配置复杂: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正成为跨平台开发的务实之选。


在线工具推荐

本站提供浏览器本地工具,免注册即可试用 →

#Kotlin多平台#KMP#跨平台开发#Compose Multiplatform#2026#编程语言