资讯动态

别再说 Flutter 是唯一选择了——KMP 正在悄悄抢走它的地盘

发布时间:2026/8/22 5:13:15 来源:尧图企业网站定制
一个反常识的问题如果我问你2024 年之后跨端移动开发的主流方案是什么十个人里有八个会说 Flutter。毕竟 Google 背书、生态成熟、UI 一致性强这几乎已经是行业共识。但我最近遇到一件事让我重新想了想这个问题一位在大厂做 Android 的朋友主导把团队的某个核心模块迁到了 KMPKotlin Multiplatform Mobile不是因为 Flutter 不够好而是因为他说了一句话——“我不想用另一套语言描述我的业务逻辑。”这句话戳到我了。Flutter 你写的是 DartKMP 你写的是 Kotlin——而 Android 工程师本来就在写 Kotlin。这不只是语言熟悉度的问题更是一个关于代码归属感和架构融合度的深层选择。今天这篇文章我想从一个 Android 工程师的视角聊聊 KMP 在真实项目中的落地体验以及它和 Flutter 之间那些真正重要的差异——不是官方文档上的那种而是干活时你会遇到的那种。 KMP 是什么先搞清楚它在解决什么问题很多人第一次接触 KMP 会有一个误解以为它是 Flutter 的竞争对手能做到一套代码跑全端 UI。其实不是至少不完全是。KMP 的核心定位是共享业务逻辑UI 各平台自己来。它的架构分层很清晰层次AndroidiOS共享UI 层Jetpack Compose / XMLSwiftUI / UIKit❌各自实现ViewModel / PresenterKotlin ViewModelKotlin ViewModel通过 KMP✅ 可以共享业务逻辑 / 领域层Kotlin 编写完全共享✅ 完全共享数据层网络/本地存储Ktor SQLDelight 跨平台✅ 完全共享换句话说KMP 让你把那些真正费脑子的部分——业务规则、数据处理、状态管理——写一次然后双端复用。UI 嘛Android 继续用 ComposeiOS 继续用 SwiftUI各自顺滑互不干扰。而 Compose Multiplatform 是 KMP 的 UI 扩展让你可以选择把 Compose UI 也共享到 iOS 端。这是个可选项不是强制的。 实战落地一个真实的模块迁移案例我们来看一个实际场景把一个用户积分计算模块从 Android 原生迁移到 KMP 共享模块同时对接 iOS 端。第一步创建 KMP 共享模块项目结构大概长这样shared/ ├── commonMain/ │ └── kotlin/ │ └── com/example/points/ │ ├── PointsRepository.kt # 共享业务逻辑 │ ├── PointsCalculator.kt # 核心计算 │ └── model/ │ └── UserPoints.kt # 数据模型 ├── androidMain/ │ └── kotlin/ │ └── com/example/points/ │ └── AndroidPointsDataSource.kt # Android 特有实现 └── iosMain/ └── kotlin/ └── com/example/points/ └── IosPointsDataSource.kt # iOS 特有实现第二步在 commonMain 写共享业务逻辑// commonMain - PointsCalculator.kt class PointsCalculator { fun calculate( basePoints: Int, multiplier: Double, bonusEvents: List ): PointsResult { val base (basePoints * multiplier).toInt() val bonus bonusEvents.sumOf { it.points } val total base bonus return PointsResult( basePoints base, bonusPoints bonus, totalPoints total, level determineLevel(total) ) } private fun determineLevel(points: Int): UserLevel when { points 10000 - UserLevel.PLATINUM points 5000 - UserLevel.GOLD points 1000 - UserLevel.SILVER else - UserLevel.BRONZE } } data class PointsResult( val basePoints: Int, val bonusPoints: Int, val totalPoints: Int, val level: UserLevel ) enum class UserLevel { BRONZE, SILVER, GOLD, PLATINUM }第三步处理平台差异——expect/actual 机制KMP 最核心的跨平台机制就是expect/actual。在 commonMain 里声明接口期望各平台提供实现// commonMain - Platform.kt expect class PlatformContext expect fun getPlatformName(): String expect fun getCurrentTimeMillis(): Long// androidMain - Platform.android.kt actual class PlatformContext(val context: Context) actual fun getPlatformName(): String Android ${Build.VERSION.SDK_INT} actual fun getCurrentTimeMillis(): Long System.currentTimeMillis()// iosMain - Platform.ios.kt actual class PlatformContext actual fun getPlatformName(): String UIDevice.currentDevice.systemName() UIDevice.currentDevice.systemVersion actual fun getCurrentTimeMillis(): Long (NSDate().timeIntervalSince1970 * 1000).toLong()第四步网络请求用 Ktor// commonMain - PointsApiClient.kt class PointsApiClient { private val client HttpClient { install(ContentNegotiation) { json(Json { ignoreUnknownKeys true }) } install(HttpTimeout) { requestTimeoutMillis 10_000 } } suspend fun fetchUserPoints(userId: String): UserPoints { return client.get(https://api.example.com/points/$userId).body() } suspend fun syncPoints(userId: String, points: PointsResult): Boolean { val response client.post(https://api.example.com/points/sync) { contentType(ContentType.Application.Json) setBody(SyncRequest(userId, points.totalPoints)) } return response.status.isSuccess() } }注意这段代码在 Android 和 iOS 上完全一样不需要任何修改。Ktor 底层会自动选择对应平台的 HTTP 引擎Android 用 OkHttpiOS 用 NSURLSession。第五步iOS 端调用——Kotlin 编译成 FrameworkKMP 会把共享模块编译成一个.xcframeworkiOS 侧直接 import 使用// iOS Swift 代码 import shared // 导入 KMP 编译的 Framework class PointsViewController: UIViewController { private let calculator PointsCalculator() private let apiClient PointsApiClient() func loadPoints(userId: String) { // 直接调用 Kotlin 编写的共享代码 Task { let userPoints try await apiClient.fetchUserPoints(userId: userId) let result calculator.calculate( basePoints: Int32(userPoints.base), multiplier: userPoints.multiplier, bonusEvents: userPoints.events ) await updateUI(result: result) } } }iOS 工程师看到这段代码的第一反应通常是这跟调普通 Swift 库没什么区别。这正是 KMP 的设计目标——对 iOS 侧几乎透明。⚔️ KMP vs Flutter真正的核心差异在哪聊了这么多 KMP 的实现现在到了最关键的问题我到底该选哪个先上对比表然后逐条说我的看法维度KMPFlutter语言KotlinAndroid 原生语言Dart专为 Flutter 设计UI 共享可选Compose Multiplatform强制所有 UI 用 Flutter原生体验极高UI 完全原生中等自绘引擎非原生组件iOS 集成编译为 Framework无缝集成需要 FlutterEngine有额外开销渐进式迁移非常友好模块级别替换困难通常需要整体重写团队要求Android 工程师上手快iOS 需要 Kotlin 学习全端都需要学 Dart生态成熟度快速成长部分库仍在完善非常成熟pub.dev 库极丰富调试工具链Android StudioIDE 支持一流VS Code DevTools体验良好热重载Android 侧有iOS 侧弱全端支持体验极佳公司背景JetBrains 主导Google 主导光看表格可能还是模糊我来说几个更有感触的点差异一KMP 不强迫你放弃原生 UI这是我认为 KMP 最被低估的优势。Flutter 的思路是我来接管所有 UI它自己画每一个像素所以在某些平台上会有不够原生的观感——比如 iOS 上 Flutter 的 Material 组件默认不跟 iOS Human Interface Guidelines 走。KMP 的思路恰恰相反UI 是你的逻辑是共享的。你的 iOS 用 SwiftUI你的 Android 用 Compose两边都是原生渲染原生体验。这对于有严苛 UI 质量要求的 App比如金融、医疗类非常重要。差异二渐进式迁移是 KMP 的杀手锏现实中很少有团队能从零起步大多数面临的是我有个跑了 3 年的 App怎么引入跨端。Flutter 基本上是个全或无的选择混合接入 FlutterEngine 的成本相当高性能也存在损耗。KMP 天然支持渐进式你可以先把网络层迁到 KMP 共享其他不动下个季度再把业务逻辑层迁过来UI 层爱动不动。每一步都是可独立验证的小步骤风险极低。差异三iOS 侧的开发者体验差距正在缩小KMP 早期被诟病的一点是 iOS 侧体验差——协程暴露给 Swift 的方式比较别扭编译时间长错误提示不够友好。但这两年改善明显• SKIESwift Kotlin Interface Enhancer让协程、Flow 等可以直接映射到 Swift 的 async/await 和 AsyncSequence• 编译产物从 .framework 升级为 .xcframework多架构支持更好• Xcode 插件开始成熟KMP 代码在 Xcode 里也能跳转、提示当然Flutter 的热重载体验依然是 KMP 短时间内很难超越的——写 UI 时秒级预览开发效率高很多。 选型建议什么团队该选什么我的选型框架是这样的可以按顺序问自己三个问题•问题一你的团队主力是 Android 工程师还是全栈/前端工程师如果主力是 AndroidKMP 的学习成本几乎为零Kotlin 就是你们的日常语言如果主力是前端/全栈FlutterDart 的体系更系统学习曲线更平滑。•问题二你的 App 对原生 UI 交互要求高不高金融 App、医疗 App、与系统深度集成的工具类 App需要原生交互体验的优先 KMP游戏类、内容展示类、UI 高度定制化的Flutter 的自绘引擎反而是优势。•问题三你是新项目还是老项目改造新项目两者都可以生态成熟度上 Flutter 略占优老项目改造KMP 的渐进式迁移能力是明显优势Flutter 几乎必须重写。实际落地建议对于大多数有 Android 背景的团队我推荐先用 KMP 共享数据层和业务逻辑层网络、存储、领域模型UI 层暂时不动。这个改造成本极低收益立竿见影——iOS 和 Android 的业务 bug 从此只需要修一次。 KMP 的局限别被我说得太美好当然KMP 不是银弹有几个真实的坑需要说•编译速度KMP 项目的增量编译相比纯 Android 项目慢iOS 端的 framework 编译尤其耗时CI/CD 需要做好缓存策略•多线程模型iOS 侧的 Kotlin/Native 对多线程有一些限制Frozen Objects 问题虽然新版本有所改善但如果你的共享代码涉及复杂并发逻辑需要额外注意•三方库生态不是所有 Android 常用库都有 KMP 版本比如 Room 的 KMP 版本Room 2.7还相对较新SQLDelight 是目前更稳妥的选择•iOS 工程师接受度有些 iOS 工程师对我的 App 里跑着 Kotlin 代码这件事心理上有抵触。这不是技术问题是团队文化问题需要提前沟通⚠️特别提醒不要在刚开始就尝试用 Compose Multiplatform 共享 UI 到 iOS这个特性虽然已经稳定但生态和工具链还在成长中坑比较多。先从共享业务逻辑层开始是最稳妥的路径。 最后说一句Flutter 和 KMP 不是非此即彼的关系它们解决的是不同层次的问题。Flutter 更擅长从零开始构建跨平台 UIKMP 更擅长让已有的 Android 逻辑平滑复用到 iOS。如果你是 Android 工程师我真心建议你花一个下午把 KMP 官方的 Getting Started 跑一遍。那种把一段 Kotlin 代码同时跑在 Android 模拟器和 iOS 模拟器上的感觉还挺上头的。不一定要在项目里立刻用但心里有这张牌下次选型的时候你会更有底气。本文为原创技术文章欢迎转载请注明出处。如有问题或建议欢迎在评论区留言交流。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价