恰逢最近 Google I/O 和 KotlinConf 2025 ,KMP 社区又再度活跃起来,结合前段时间 Compose Multiplatform iOS 稳定版发布 ,其实现阶段的 KMP 对于大多数开发者来说已经足够成熟了,至少在 Android 和 iOS 领域,还有 klibs.io 的支持下,可用性不再是问题。
而相信大多数人都很关心,现在有哪些企业在使用 KMP,或者说,国内有什么企业在使用?关于这个,美团大佬的 kmp-case-studies-cn 就展示了部分案例:
- 美团:收银智能版、点餐助手智能版,通过 KMP 实现了共 6 个终端 App 的逻辑层复用
- 携程:2021 年初开始使用 KMP
- B站: Android、iOS、鸿蒙三端采用 KMP 逻辑跨平台,并使用了 CMP
- 腾讯:开源有 NTCompose、Kuikly 等框架
- 快手:快手鸿蒙版应用采用 KMP 逻辑跨平台 + ArkUI 原生 UI 开发
- 阿里:淘宝和支付宝
- Kimi:通过 KMP+CMP 跨端开发方案,实现了 PC 、鸿蒙 和 Android 适配
另外,在 Jetbrains 的官方 case-studies 里,也展示了百度、美团和B站的相应案例:
甚至在 KotlinConf 2025 上,B站也是 C 位展示:
而在本次 Google I/O 上,官方也表示,去年 Google Workspace 开始试用 KMP,现在它正在 iOS 上的 Google Docs 应用中运行,目前看来 App 的运行时性能与之前相比好了不少。
JetBrains 和 Google 合作这么久,终于也让 Google 在自家产品用上了 KMP 。
那么可能很多人会问了,既然 KMP 看起来还不错,那现在使用 KMP 还会遇到什么问题吗?我只能说:
一般不会有什么问题,因为有问题的时候也不是一般人能解决。
当然,有一点比较特殊的是,KMP 和广大 Android 熟悉的 Kotlin 还是有些差异,至少在 Android 和 iOS 两个平台,它们的差异还是很明显,毕竟一个是 Kotlin/JVM ,一个是 Kotlin/Native。
大家都知道,Kotlin 最强大的就是它的编译器,所以它有 Kotlin/JVM、Kotlin/Native、Kotlin/S、Kotlin/Wasm 多种语言支持,而在 iOS 上,Jetbrains 选择了 Kotlin Native 路线。
而之所以选择 Kotlin/Native ,当然也是为了更好的性能,总不能真的在 iOS 跑 JIT 支持的虚拟机吧?
其实 JIT 运行在 iOS 平台这个路线,其实 Flutter 上也有企业测试过,比如做热更新的 Shorebird ,它们一开始就在 iOS 上测试过类 JIT 的运行,但是效果不佳。
不就是 JIT 模式就性能一定差,在 Flutter debug 模式下感受到的性能很差,实际上导致慢的主要原因是因为 Flutter 框架里有着许多一致性检查/断言,而这些导致性能极具下降的检查/断言仅在 debug 模式下启用,这才是缓慢的主要来源。
对于 JIT 模式主要差别是需要预热,所以程序可能需要一定的时间才能达到最佳性能,同时需要更多内存占用,但是从理论峰值性能考虑,其实并不会输于 AOT。
而在 iOS 平台,KMP 作为外来户,使用 JIT + Skia 的性能肯定会受到限制。
而 AOT 的特点是启动速度非常快,无需预热就可以达到最佳性能,所以 AOT 非常适合 UI 场景,因为 UI 无法容忍 JIT 的不可预测性和预热时间。
那么这也是目前比较典型的问题,KMP 在 Android 和 iOS 的支持可能存在「隐性」的不完全一致,虽然 Kotlin/Native 与 Kotlin/JVM 的编译器共享前端(负责代码解析、名称解析和类型推断等),但对应 Kotlin/Native 后端针对 LLVM 位码生成是完全不同的 ,这就带来了一些奇奇怪怪的差异。
KMP 针对 KN 在 iOS 提供了一套标准库支持。
例如 Kotlin 2.1 中对 typeOf()
函数行为进了统一,因为在此之前 typeOf
函数在某些极端情况下,Kotlin/Native 和 Kotlin/JVM 的行为是不同的,而导致这个不同的原因是:内联发生在不同 platforms 上 pipeline 的不同部分:
- 在 Kotlin/JVM 上,它发生在字节码中的 erased types 上
- 在 Native 上,它发生在 IR 中
import kotlin.reflect.*
class Pair<A, B>(val x: A, val y: B)
inline fun <reified T1> typeOfX(x: T1) = typeOf<T1>()
inline fun <reified T2, T3> typeOfPair(x: T2, y: T3) = typeOfX(Pair(x, y))
// returns "Pair<kotlin.String, T3>" in K/Jvm
// returns "Pair<kotlin.String, Any?> in K/N
fun test() = typeOfPair("1", 1).toString()
这也就是导致了 2.1 之前,这个隐性问题在 JVM 和 K/N 之前出现了细微差异:
而 JVM 和 Kotlin/Native 带来的差异也体现在 OKHttp ,例如最初 OkHttp 计划在 5.0 版中支持 Kotlin Multiplatform,包括 Kotlin/Native, 然而最终被放弃,因为维护人员发现无法在 Kotlin/Native 上使用现有的 HTTP 客户端引擎,同时团队也还没准备好专门为 Kotlin/Native 开发 TLS API。
当然,Kotlin 也有自己 ktor ,所以不用 OKHttp 也不是什么大问题,当然,小问题就是也许你 Android 也需要用 ktor :
Ktor 3 对内核进行了重大改进,包括高达 3 倍的 I/O 性能提升、增强的配置支持以及 server-sent events,、WebAssembly 支持等新功能。
此外,例如 Kotlin/Native 对反射的支持非常有限 ,其中 KClass
的内省功能主要提供 simpleName
、qualifiedName
、isInstance
、cast
和 safeCast
等基本信息 ,而完整的内省功能,如列出成员(KClass.members
)、构造函数(KClass.constructors
)、嵌套类(KClass.nestedClasses
)、超类型(KClass.supertypes
)等,通常只支持 JVM 默认,当然也不支持 Class.forName
的功能。
另外 GC 也有很大差异,不过一般不会影响包开发者,影响了你也没辙。
所以 Kotlin/Native 模式下,Kotlin/Native 代码则作为独立的本地可执行文件运行,不依赖虚拟机 ,并自行管理内存,拥有自己独立的内存模型和垃圾回收机制,都体现出它整个后端和 JVM 的差异,也体现出了 Android 和 iOS 在后端支持上的差异。
另外,作为 AOT,Kotlin/Native 可是相当吃内存,在之前 KT-77683 就有报告,在使用 CMP iOS 时 AS 出现 38G 的内存占用:
这是因为 Kotlin/Native 在 iOS 整个构建工具链(Gradle、Kotlin编译器、LLVM、Xcode构建系统组件)上本身就是分吃内存,因为 Kotlin/Native 的 AOT 编译过程,涉及对整个代码库的深入分析和到原生代码的转换 。
所以在 iOS 端,如果你电脑内存不够,很容易就会看到
Compilation failed:Java heap space
最后,现在使用 KMP 开发鸿蒙的大厂也不少,主流的有 Kotlin/JS 和 Kotlin/Native 两个路线,但是像 B 站,就是因为 Kotlin/JS 的性能问题,最终转到 Kotlin/Native。
使用 Kotlin/Native 肯定性能更好,但是兼容成本也更高,因为在鸿蒙上需要使用 llvm 进行支持,而直观的问题就是,KMP 官方的 llvm 升的还挺快,比如现在的 llvm 16 和马上要来的 #KT-75829 llvm 19 ,而鸿蒙平台目前是 llvm 15 :
比如当你需要升级 iOS 支持,甚至使用 Swfit Export 的时候,就需要考虑是稳 iOS 还是保鸿蒙平台:
上面的 Swift Export 的第一个实验性版本将在 Kotlin 2.2.20 中出现,主要是解决之前缺乏直接的纯 Swift 互操作性,需要通过 Objective-C 桥接时 Swift 泛型的限制。
暂时看性能还有点问题,但是前景是好的。
说了那么多问题,说点正面的:Amper ,它作为 JetBrains 实验性的 Kotlin 和 JVM 构建工具,主要是为了在简化 Kotlin 和 Kotlin Multiplatform 项目的构建配置,提升用户体验和 IDE 支持,注意,它当前目标是改进用户体验,而不是创建一个全新的独立构建工具,目前看来还是依赖 Gradle ,后期会不会完全独立就不知道了:
另外,Kotlin/Wasm 得到了不少的改进,具有更快的增量构建、更小的输出二进制文件和更好的开发人员体验,目前 Kotlin/Wasm 和 Compose Multiplatform for Web 预计将在今年晚些时候进入 Beta 版:
接着还有全新的 KMP 插件,终于可以直接在 IDE 中创建新的 KMP 项目,还可以选择原生 UI 或共享 UI 与 Compose Multiplatform 共享:
自从 Fleet 被放弃作为 KMP 专用 IDE 后,官方终于回到正确的路线,现在对于同时使用 Kotlin 和 Swift 的项目,插件可在 IDE 中实现跨语言导航、语法高亮显示、快速文档和调试:
Android Studio 和 IntelliJ IDEA Ultimate 中已经提供了对 iOS 的调试支持, IntelliJ IDEA Community Edition 中的支持会稍晚一些。
Kotlin Multiplatform 插件暂时只支持 IntelliJ IDEA 2025.1.1.1
和 Android Studio Narwhal 2025.1.1
的 JetBrains Marketplace 获得,而且暂时仅支持 macOS, Windows 和 Linux 已经在路上。
需要启用 K2 模式 。
最后,Kotlin 正在扩展到更多的开发环境 – 官方 Kotlin LSP 和适用于 VSCode 的新 Kotlin 扩展也正在推进,虽然仍处于早期阶段,但它已经包括对代码完成、导航、检查、快速修复、Java 互作性和基本项目导入的基本支持,计划在今年晚些时候发布 Alpha 版本,对于 KMP 的支持应该会更晚一些。
最后
从目前来看,客户端领域还是很推荐使用 KMP 进行开发,前面说这些问题不是让你放弃,而是让你心里有个底,正常说来其实一般人都不会遇到什么大问题,而是否使用 CMP 就见仁见智了,目前国内 KMP 大厂使用的还比较客观,但是 CMP 的使用率其实并不高,使用 CMP 需要的技术积累会更高,特别适配鸿蒙的成本上,所以我个人更推荐 KMP ,至于 CMP 或者可以再稳稳,如果你想上生产环境。
那么,2025 你准备好 KMP 了么?