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#编程语言