Kotlin 跨平台开发中的权衡:KMP 值不值得选,看清这几层就够了

巷口听风
巷口听风
发布时间:2026-08-25| 47人浏览过
原创

前言

跨平台开发从来不是单纯比拼“谁能复用更多代码”,真正难的是在复用率、原生体验、性能和团队迁移成本之间找到可执行的平衡。Kotlin Multiplatform(KMP)之所以值得单独评估,正因为它没有强迫团队一次性放弃原生,而是把共享逻辑、共享 UI 和平台实现拆成了可逐步决策的几层。

跨平台开发一直绕不开一个老问题:想要更高的代码复用率,往往就要在原生体验、性能或团队迁移成本上做交换。Kotlin Multiplatform(KMP)这几年之所以被频繁讨论,正是因为它试图把这道选择题改成分层决策:哪些代码共享,哪些能力保留原生,由团队自己控制。

如果你正在评估 Android 与 iOS 的双端方案,或者已经有原生项目、又不想一次性重写整套技术栈,KMP 值得单独看待。它和 Flutter、React Native 的出发点并不相同,判断它是否合适,关键要看你的共享目标落在哪一层,以及团队是否能接受当前生态的边界。

什么是 Kotlin 跨平台

Kotlin Multiplatform,通常简称 KMP,本质上是一套“共享通用代码,同时保留平台能力”的开发方式。它不是那种彻底屏蔽平台差异的统一框架,也不是要求你把 Android、iOS 全部改写成同一种 UI 技术。

KMP 项目结构与 expect/actual 协作关系图
KMP 的模块结构与实现路径用模块划分和 expect/actual 关系说明 KMP 如何在共享代码与平台实现之间分工。

它更像是一种分层方案:把业务逻辑、数据处理、网络访问这类与平台关系不大的部分放到共享层;把平台 API、系统能力接入、以及是否采用原生 UI,则交给各端自行决定。Android 侧依然可以使用 Kotlin,iOS 侧也依然可以使用 Swift 或 Objective-C 编写界面。

这一点很重要,因为它意味着 KMP 并不要求团队在“全原生”和“全跨平台”之间二选一。你可以只共享逻辑,也可以进一步借助 Compose Multiplatform(CMP)共享 UI;是否走到这一步,取决于产品目标,而不是框架强制。

它是如何工作的

一个典型的 KMP 项目,通常会把代码按平台与共享范围拆成不同模块:

  • commonMain:放共享代码,只编写一次,供所有目标平台复用,常见内容包括业务逻辑、网络请求、数据模型等。
  • androidMain:放 Android 端实现,适合接入 Android API,也可在这里编写 Android 的 UI。
  • iosMain:放 iOS 端实现,适合接入 iOS API,并与 Swift / Objective-C 界面层协作。

KMP 的关键机制是 expect/actual。做法是先在共享层声明“我需要这样一个能力”,再由不同平台分别补上真实实现。

例如,你可以在 commonMain 中声明一个生成唯一标识符的函数,然后在 Android 端使用 UUID.randomUUID() 实现,在 iOS 端使用 NSUUID().uuidString 实现。共享层统一 API,平台层各自调用最合适的原生能力,这就是 KMP 的基本运行方式。

这种结构的意义在于:代码可以共享,但平台能力不会被抹平;应用仍然编译到目标平台所需的原生格式,而不是依赖额外的解释层来兜底。

KMP 到底解决了什么问题

1. 降低重复开发成本

原生双端开发最大的现实问题,不只是“要写两套代码”,更是功能、规则、接口、测试都可能重复一遍。只要产品的核心逻辑在多个平台上保持一致,共享层就能直接减少这部分重复劳动。

把业务逻辑、网络层、数据处理放进 commonMain 后,同一套能力不需要分别在 Android 与 iOS 上重复实现,也不用为同一段规则维护两份测试。这样做的直接收益,是降低重复错误、减少逻辑漂移,也让质量保证流程更集中。

不过这并不是 KMP 独有的优势。Flutter 和 React Native 同样能做到高比例代码复用,所以如果团队只看“是否减少重复开发”,KMP 并不会天然胜出。

2. 兼顾共享与原生性能

KMP 的一个核心卖点,是它不通过桥接层来执行共享逻辑。共享的 Kotlin 代码会直接编译为目标平台需要的格式:Android 侧生成 JVM 字节码,iOS 侧生成原生二进制。

KMP 落地案例中的共享边界与保留原生能力示意图
大公司如何划定 KMP 的使用边界用企业案例展示 KMP 并不是全量替代,而是围绕业务逻辑、SDK 与平台差异做共享边界划分。

这和 React Native 的思路明显不同。后者依赖 JavaScript 桥与原生组件通信,复杂场景下桥接开销可能成为瓶颈;而 KMP 这类直接编译方案,在执行路径上更接近原生应用。

如果团队对动画流畅度、大量业务计算、复杂数据同步等场景较敏感,KMP 在性能层面通常更容易被接受。它不是把平台换掉,而是在平台之上共享代码。

3. 可以逐步引入,而不是一次性重写

不少团队迟迟不愿尝试跨平台,并不是不认可共享价值,而是承担不起“一次性切换技术栈”的风险。KMP 在这里提供了更现实的落地路径。

Flutter 使用 Dart,React Native 使用 TypeScript 或 JavaScript,通常都更接近一种整体性迁移;KMP 则可以只从某一层开始,比如先抽出网络层、配置层、规则引擎、支付流程或某个独立功能模块。

这种逐步采用的方式,对已有原生项目尤其重要。它允许团队先验证收益,再扩大范围,而不是在一开始就把 UI、构建流程、团队协作方式全部重置。

4. 对 Android 团队迁移门槛更低

由于 Kotlin 已经是 Android 生态中的主流语言,很多 Android 团队并不需要重新学习一门陌生语言,就能进入 KMP 的实践阶段。对这类团队来说,KMP 更像是能力扩展,而不是技术重启。

真正的门槛通常不在 Android 侧,而在跨端协作方式、模块拆分边界,以及 iOS 团队是否愿意接受新的语言与构建体系。

和 Flutter、React Native 相比,KMP 的差别在哪里

这三类方案都在解决“多平台应用如何减少重复开发”,但它们的路线并不一样,最关键的差别集中在 UI、运行机制和采用方式上。

Flutter、React Native 与 KMP 的对比关系图
三种跨平台路线的核心差异聚焦语言、UI 渲染、性能与采用方式四个维度,帮助读者快速判断三类方案的差异。
特性FlutterReact NativeKMP
语言DartJavaScript / TypeScriptKotlin
UI 渲染使用 Skia 引擎渲染自己的 UI通过 JS 桥控制原生 UI 组件可使用原生 UI(SwiftUI/Compose)或共享 UI(Compose Multiplatform)
性能优秀,编译为原生代码,无需桥接良好,但 JavaScript 桥可能成为瓶颈优秀,编译为平台原生格式,无需桥接
采用方式完全投入完全投入逐步采用

如果把三者放到同一张图里看,可以把 KMP 理解为一条“中间路线”:它不像 Flutter 那样自带一整套统一 UI 体系,也不像 React Native 那样强调跨语言桥接,而是把共享重点放在逻辑层,并为共享 UI 留出可选路径。

这也意味着它更依赖团队自己做边界设计。想尽量保留平台原生体验,可以只共享逻辑;想提高复用比例,可以引入 CMP 共享界面。灵活性是它的优点,但灵活性本身也会增加决策复杂度。

iOS 侧进入了什么阶段

过去很长一段时间里,KMP 在 iOS 方向上的主流模式都是“共享逻辑,界面原生实现”。这套模式已经足够实用,但也意味着 UI 层仍要分别开发,团队对共享上限有明确天花板。

这一情况随着 CMP 的推进发生了变化。随着 1.8.0 稳定版发布,截至 2025 年 5 月 6 日,用于 iOS 的 CMP 到达了一个可用于生产环境的稳定里程碑。

这件事的重要性在于:现在不仅业务逻辑能共享,UI 也开始具备大规模共享的现实条件。借助 Jetpack Compose 与 Compose Multiplatform,开发者可以使用同一套 Kotlin 代码为 Android 和 iOS 定义界面。

对于新项目来说,这让 KMP 的价值主张变得更完整了。过去它更像“共享逻辑方案”,现在它开始具备“构建整个应用”的能力。当然,这并不等于所有 iOS 项目都应该立刻共享 UI,因为“能共享”不代表“必须共享”。

共享 UI 不等于放弃原生界面

KMP 在 iOS 上真正有吸引力的地方,不是强推单一路线,而是允许混用。某些页面继续使用原生 SwiftUI/UIKit,另一些页面改用 Compose,这是可以并存的。

如果要在原生 SwiftUI 应用中嵌入 CMP 页面,可以把可组合 UI 包装在 ComposeUIViewController 中,再通过实现 UIViewControllerRepresentable 的结构体在 SwiftUI 中接入。

反过来,如果要在 Compose 界面中嵌入原生 SwiftUI 视图,则可以先通过 UIHostingController 托管原生视图,再使用 UIKitView 将其嵌入到 Compose 布局中。

这类互操作能力的价值很现实:它让团队不必在“全共享 UI”与“全原生 UI”之间做激进切换,而是可以围绕页面、模块、迭代节奏来安排迁移顺序。

真实公司怎么使用 KMP

KMP 的讨论价值不只来自理念,还来自一批已经公开经验的大型公司。它们的共同点不是把所有代码都塞进共享层,而是把最值得统一的部分优先抽出来。

Netflix:先统一业务逻辑,再考虑薄 UI 层

Netflix 从 2020 年 10 月 就开始使用 KMP。它的核心目标不是追求“一个框架写完所有端”,而是统一 Android 与 iOS 中原本高度相似的业务逻辑与架构。

我们的 Android 和 iOS 应用程序有着共享的架构,两个平台上编写的业务逻辑相似,甚至在某些情况下完全相同。—— Netflix

公开资料显示,Netflix 做到了代码与底层平台 50% 的解耦。这说明 KMP 在大型应用中的一个现实角色,是帮助团队先把核心逻辑收拢,再逐步探索 UI 层是否进一步变薄、是否继续提高共享比例。

他们还把 KMP 用在内部的 Prodicle 应用中,支撑电视与电影项目制作流程。这类案例说明,KMP 并不只适合面向消费者的 App,也适合业务复杂、规则重、平台一致性要求高的内部工具。

麦当劳:从一个能力点切入,最后扩大到整套应用

McDonald’s 最初是在给应用加入应用内支付能力时引入 KMP,当时项目中使用的名称还是 KMM。这是一种很典型的落地路径:先拿一个高价值、跨端差异又相对可控的模块做试点。

将 KMM 集成到应用程序流程中,使我们能够在一个地方开发解析和存储逻辑,此外还能开发在每个平台上正确显示本地化数据和产品所需的业务逻辑。—— 麦当劳

在验证方法可行后,麦当劳把 KMP 的使用扩展到更多服务,尤其是地区化商品与数据处理这类需要跨市场统一规则、又必须兼顾本地差异的逻辑。最终,他们重写了整套应用以采用 KMP,并把原本独立的 Android 与 iOS 团队整合成了一个更统一的移动团队。

这个案例很能说明 KMP 的组织价值:共享代码并不只是省工时,它还会反过来影响团队结构、职责分工以及跨端协作方式。

飞利浦:共享 SDK,但保留蓝牙原生实现

Philips 在 2018 年 采用 KMP,为互联消费产品和个人健康产品开发共享 SDK,用于设备通信与数据同步。像牙刷、空气净化器这类硬件连接场景,本身就很适合把协议、同步、业务规则收敛到共享层。

蓝牙低功耗接口存在很大差异,以至于无法设计出一种能同时适配两者的方案。所以在这方面,我们仍将采用原生开发方式。—— 飞利浦

但他们也明确保留了蓝牙低功耗相关 API 的原生实现。原因很简单:平台差异太大,强行统一反而会带来更多复杂度。

这正是评估 KMP 时最该重视的一点:它不是“越多共享越好”,而是“该共享的共享,不适合共享的就留在平台侧”。飞利浦的案例比成功叙事更有参考价值,因为它清楚展示了边界感。

采用 KMP 之前要看清哪些限制

KMP 的路线很有吸引力,但它并没有消除所有权衡。真正落地时,挑战通常集中在生态、协作和互操作细节上。

生态成熟度仍在追赶

与 Flutter、React Native 相比,KMP 的一个现实短板是生态规模仍偏小。核心能力已经比较稳,但一旦项目涉及更细分的需求,例如高级蓝牙交互、后台服务、后台定位,合适的 KMP 库并不总是现成可用。

这时团队往往需要自己封装原生能力,或者为原生方案写一层包装。技术上可行,但会抬高维护成本,也会降低“写一次到处运行”的实际比例。

iOS 团队需要适应 Kotlin 和 Gradle

对 Android 团队来说,KMP 往往是顺势延伸;对 iOS 团队来说,却可能意味着要接触新的语言、新的构建工具和新的调试习惯。Kotlin 与 Gradle 在 Android 世界很常见,但对不少 iOS 开发者而言并不熟悉。

这不是无法解决的问题,但必须计入迁移成本。很多团队低估的并不是技术实现本身,而是协作模式改变带来的磨合期。

Kotlin/Native 与 Swift/Objective-C 互操作有边界

Kotlin/Native 和 Swift/Objective-C 之间并不是毫无损耗地互通。它依赖的是与 Swift/Objective-C 的间接互操作,一些 Kotlin 特性在 Objective-C 里并没有完全对等的表达方式。

泛型就是一个典型例子。跨边界转换后,类型信息可能丢失,开发者需要额外注意传递的类型,并在接口设计与校验逻辑上预留处理空间。如果团队直到开发中后期才意识到这些差异,返工成本会比较高。

工具链仍在进步,但还不算完全无感

虽然相关插件和开发体验在持续改善,JetBrains 也在积极推进工具支持,但 KMP 当前的开发流程仍没有原生开发工具那样顺滑。尤其是在多模块构建、跨平台调试、IDE 集成体验上,团队通常需要一段时间建立自己的工作流。

不过,这个问题的变化速度也很快。随着采用率提升,社区经验、开源库与配套工具都在增加,很多早期障碍已经比过去轻得多。

怎么判断 KMP 适不适合你的项目

KMP 最值得关注的地方,不是它能不能替代所有跨平台方案,而是它把跨平台开发里的权衡重新分配了。团队可以先共享业务逻辑,再决定是否共享 UI;可以保留原生体验,也可以在合适的部分提高复用比例。

如果你的项目最看重原生性能、需要长期接入平台能力,且已有 Android 原生积累,KMP 往往比“整体迁移到另一套框架”更容易落地。尤其是在业务规则复杂、双端逻辑高度一致的场景里,它的收益通常很明确。

但如果项目高度依赖某些生态尚不成熟的能力,例如高级蓝牙低功耗交互或复杂后台服务,那么平台专属实现依然不可避免。换句话说,KMP 更适合被视为一种渐进式架构工具,而不是一个能抹平所有差异的万能答案。

最后,如果你在评估可用库的现状,可以关注 klibs.io 这类 KMP 生态索引站点,看看目标能力是否已有合适实现,再决定共享边界。对多数团队来说,真正重要的不是追求最大共享率,而是找到共享收益与平台复杂度之间的合理平衡。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。