Kotlin Multiplatform:什么是它,shared module 和 expect/actual

作者: IT Sectr 发布日期: 2026-02-11 阅读时间: 11 分钟

Kotlin Multiplatform(KMP)— JetBrains 技术,将通用 Kotlin 代码直接编译为 iOS、Android、Web 和 Desktop。与 Flutter 和 React Native 不同,KMP 不替换原生 UI — 通用逻辑被提取到 shared module 中,每个应用程序的界面保持原生。Kotlin Multiplatform documentation — 配置模块和 expect/actual 机制的主要参考指南。

要点

  • KMP — 在 Kotlin 中使用 expect/actual 实现共享逻辑,用于平台 API,无需替换原生 UI
  • Shared module — 包含网络请求、数据库、验证和业务逻辑代码的 Gradle 模块,适用于所有平台
  • Expect/actual — 在通用代码中声明平台 API 并针对每个目标提供实现的机制
  • iOS integration — shared module 通过 Kotlin/Native 编译为 Apple framework
  • KMP vs KMM — Kotlin Multiplatform Mobile(移动端焦点)现在是通用 Kotlin Multiplatform 的一部分

什么是 Kotlin Multiplatform?

Kotlin Multiplatform — 交叉编译技术,允许用 Kotlin 编写通用代码并将其编译为不同平台:JVM(Android)、LLVM(iOS、macOS、watchOS)、JavaScript(Web)和原生二进制文件(Linux、Windows)。KMP 不是 UI 框架 — 它解决的是业务逻辑的重用问题,而不是界面。

KMP 的架构围绕 shared module 构建 — 一个 Gradle 模块,包含具有平台无关代码的 commonMain 和针对每个目标的 source sets(androidMain、iosMain、desktopMain)。根据 JetBrains 2025 年的数据,超过 40% 的新 Kotlin 项目使用 KMP 在平台之间共享代码。

Kotlin Multiplatform Mobile(KMM)— 以前用于 iOS+Android 移动场景的名称。从 Kotlin 2.1+ 开始,KMM 术语已被通用 Kotlin Multiplatform 取代,因为该技术已超越移动开发的界限。Netflix、McDonald's 和 VMware 在生产中使用 KMP 在移动应用程序之间共享代码。

Expect/actual 机制:架构

Expect/actual — KMP 处理平台代码的关键机制。在 commonMain 中声明 expect 声明(函数、类、属性),在每个特定于平台的 source set(androidMain、iosMain)中声明 actual 实现。编译器检查每个 expect 在每个目标平台上是否有对应的 actual。

kotlin
// commonMain — 平台 API 的声明
expect fun getPlatformName(): String

expect class PlatformContext(val appVersion: String)

// androidMain — Android 的 actual 实现
actual fun getPlatformName(): String = "Android \${Build.VERSION.SDK_INT}"

// iosMain — iOS 的 actual 实现
actual fun getPlatformName(): String =
    UIDevice.currentDevice.systemName

Source sets 层次结构 在 KMP 中允许创建中间层:例如,iosArm64Main(物理 iOS 设备)和 iosSimulatorArm64Main(模拟器)具有共同的 iosMain。来自 commonMain 的代码对所有平台可用,来自 iosMain 的代码仅对 iOS 目标可用。当实现不是每个平台都不同,而是一组平台不同时,这减少了重复。

在实践中,expect/actual 用于:获取本地存储(SharedPreferences vs NSUserDefaults)、网络工作(每个平台的 HttpEngine)、文件系统访问、加密和分析。JetBrains 建议最小化 expect/actual 的数量,并将尽可能多的代码移到 commonMain 中。

Shared module:结构和 Gradle

Shared module — 带有 `org.jetbrains.kotlin.multiplatform` 插件的标准 Gradle 模块。它在 `src/commonMain/kotlin/` 中包含通用代码,在 `src/androidMain/kotlin/` 和 `src/iosMain/kotlin/` 中包含平台实现。KMP 项目还连接了依赖于 shared module 的 `androidApp` 和 `iosApp`。

kotlin
// build.gradle.kts — shared module
plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

kotlin {
    androidTarget()
    
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
            isStatic = true
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:3.1.0")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:3.1.0")
            }
        }
        val iosMain by creating {
            dependencies {
                implementation("io.ktor:ktor-client-darwin:3.1.0")
            }
        }
    }
}

KMP 的 Gradle 配置需要明确指定 iOS 目标 — x64(Intel 模拟器)、arm64(物理设备)和 simulatorArm64(Apple Silicon 模拟器)。为每个目标生成单独的 Apple framework。`kotlin("multiplatform")` 插件根据声明的目标自动配置 JVM 和 LLVM 的编译。

Ktorkotlinx.serialization — 支持通用代码的标准 KMP 库。Ktor 为每个平台提供带有引擎的 HTTP 客户端(Android 使用 OkHttp,iOS 使用 Darwin)。kotlinx.serialization 由于在 commonMain 中的多平台实现,无需 expect/actual 即可在任何平台上运行。

通过 Kotlin/Native 与 iOS 集成

Kotlin/Native — 通过 LLVM 将 Kotlin 编译为原生代码的编译器。对于 iOS,shared module 编译为 Apple framework(.framework),通过 Xcode 连接。从 Swift/Objective-C 调用通用代码通过生成的 Objective-C 头文件进行,因此 shared module 的 API 必须与 Objective-C 兼容。

iOS 集成的限制: Kotlin 集合(List、Map)转换为 NSArray/NSDictionary。具有默认参数的函数不会被导出 — 需要 overloads。对于 suspend 函数,生成基于回调的方法,使用 `@ObjCName` 并从 Kotlin 2.0+ 开始支持 async/await。

swift
// iOS 应用程序:从 Swift 调用 shared module
import shared

class ViewModel: ObservableObject {
    let repository = UserRepository()
    
    func loadUsers() {
        repository.fetchUsers(completionHandler: { result, error in
            if let users = result as? [User] {
                print("Users: \(users.count)")
            }
        })
    }
}

Shared module 在 Xcode 中的 集成通过 embed-and-framework 完成 — 生成的 `.xcframework` 被添加到 Xcode 项目中。Gradle 插件可以通过 embedAndSignAppleFrameworkForXcode 在构建时自动更新 framework。在模拟器上测试时,iosSimulatorArm64 或 iosX64 二进制文件就足够了。

KMP vs Flutter vs React Native

KMP、Flutter 和 React Native 之间的选择取决于优先级:逻辑重用还是完全跨平台。KMP 在每个平台上提供原生 UI,但需要两个代码库用于界面。Flutter 和 React Native 使用统一的 UI,但牺牲了原生性。

特性KMPFlutterReact Native
UI 框架原生(Android XML/Jetpack Compose + SwiftUI)Dart + 自有 Skia 渲染器React + 原生组件
通用代码业务逻辑、网络、数据库、验证100%(原生插件除外)100%(原生模块除外)
性能原生(无中间层)高(Skia Engine)中(JSI Bridge)
iOS 支持Kotlin/Native(优秀)优秀良好
入门门槛中(Kotlin + 原生平台)低(一种语言 + 一个 UI)低(JS/TS + React)

何时选择 KMP: 项目需要高性能 UI(游戏、地图、动画),需要重用现有原生代码,团队已经熟悉 Kotlin 和原生平台。何时选择 Flutter/RN: 预算有限的 MVP 或初创公司,单一背景的团队,UI 不需要深度原生定制。

KMP 工具和库

KMP 工具 生态系统包括适用于应用程序所有层的库:网络(Ktor)、序列化(kotlinx.serialization)、数据库(SQLDelight)、导航(Decompose)、DI(Koin)和数据存储(multiplatform-settings)。JetBrains 支持 Compose Multiplatform — 一个在所有平台上运行的 Kotlin UI 框架。

kotlin
// 使用 SQLDelight + Ktor 在 KMP 中的 Repository
class UserRepository(
    private val httpClient: HttpClient,
    private val db: AppDatabase
) {
    suspend fun syncUsers(): List<User> {
        val remote = httpClient.get("https://api.example.com/users")
            .body<List<UserDto>>()
        
        db.userQueries.replaceAll(remote.map { it.toDomain() })
        
        return db.userQueries.selectAll().executeAsList()
    }
}

Compose Multiplatform — 基于 Jetpack Compose 的 KMP UI 框架。允许用 Kotlin 为 Android、iOS、Desktop 和 Web 编写界面。2025 年,Compose Multiplatform 在 Android 和 Desktop 上达到稳定状态;iOS 目标处于测试阶段。对于具有原生 UI 的生产项目,KMP 的优势仍然是它与 Flutter 的主要区别。

常见问题

Kotlin Multiplatform 与 Kotlin Multiplatform Mobile 有何不同?

KMM — 是 KMP 针对 iOS 和 Android 的移动场景。从 Kotlin 2.1+ 版本开始,JetBrains 将这两个术语统一为 Kotlin Multiplatform,因为该技术不仅支持移动平台,还支持 Desktop 和 Web。KMM 项目继续运行,但现在已成为通用 KMP 的一部分。

KMP 可以与 SwiftUI 一起使用吗?

可以。KMP 通过 Kotlin/Native 编译为带有 Objective-C 头文件的 Apple framework。SwiftUI 将此 framework 作为普通库导入。Shared module 导出 Kotlin 类和函数,这些可以从 Swift 调用,但有一些限制(例如,Kotlin 集合会转换为 Foundation 类型)。

如何在 iOS 上测试 shared module?

在 iOS 上,shared module 通过在 iosTest source set 中的 Kotlin/Native 测试进行测试。对于 UI 测试,在 Xcode 中使用 XCTest 并导入 framework。Kotlin 测试在 commonTest 中用 kotlin.test 编写,并通过 Gradle 任务 iosSimulatorArm64Test 在 iOS 模拟器上执行。

KMP 中有哪些可用的库?

主要的 KMP 库:Ktor(网络)、kotlinx.serialization(JSON)、SQLDelight(数据库)、Koin(DI)、Decompose(导航)、multiplatform-settings(SharedPreferences/NSUserDefaults)、Apollo GraphQL、Firebase(通过 KMP-NativeCoroutines)。Compose Multiplatform 为所有平台提供 UI。

KMP 支持 Gradle 8 吗?

支持。KMP 完全兼容 Gradle 8.5+。从 Kotlin 2.1 开始,官方插件支持 Gradle 8。通过 build.gradle.kts 使用 kotlin("multiplatform") 进行配置需要 Gradle 7.6+,但建议使用 8.5 版本以获得最佳构建性能。

总结

  • Kotlin Multiplatform — JetBrains 的跨平台技术,用于共享代码,无需替换原生 UI
  • Expect/actual — 在 commonMain 中声明平台 API 并为每个目标提供实现的机制
  • Shared module — 具有 commonMain 和平台 source sets(androidMain、iosMain)的 Gradle 模块
  • Kotlin/Native 将 shared module 编译为 Apple framework,可从 Swift 和 Objective-C 调用
  • KMP vs Flutter/RN — 逻辑重用 + 原生 UI 对比统一代码库和 UI
  • Compose Multiplatform — 适用于 Android、iOS、Desktop 和 Web 的 Kotlin UI 框架
  • 生态系统 — 适用于应用程序所有层的 Ktor、SQLDelight、Koin、kotlinx.serialization、Decompose

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读