KMP全栈开发:从Android到AI Agent的技术演进与实践
一、引言:KMP的全栈演进之路
2023年秋天,我在一个跨平台项目的技术选型会议上陷入了沉思。当时的需求很明确:一套业务逻辑,要同时跑在Android、iOS、Web和桌面端,服务端还得接大模型做智能问答。团队里一半人写Kotlin,一半人写Python,技术栈割裂得像两块拼不上的拼图。
如果选Flutter,能搞定移动端和Web,但桌面和AI集成呢?如果选React Native,生态倒是丰富,但团队要额外维护两套后端——一套业务API,一套AI推理服务。正当我犹豫时,团队里一个Android开发说了一句话:“为什么不用Kotlin把两端都写了?”
这句话像一束光,照亮了一条被大多数人忽视的路:Kotlin Multiplatform(KMP)。
KMP不是新东西,但直到今天,很多开发者对它的认知还停在“跨平台移动开发”的阶段。实际上,KMP的野心远不止于此——它想做的是全栈统一语言方案。从Android UI到底层网络请求,从服务端API到AI Agent的推理编排,全部用Kotlin写。这不是未来时,而是现在进行时。
本文将带你走一遍这条完整的技术链路。我们从KMP的核心架构说起,逐步深入到Android项目改造、服务端开发、Web/Desktop多端适配,最终落脚到AI Agent——用KMP搭建一个真正的智能客服系统。这不仅是技术讲解,更是一个真实项目的完整复盘。
读完这篇文章,你将获得:
- 一张全景图:KMP在现代全栈架构中的真实位置
- 一条迁移路径:如何从现有Android项目一步步扩展到全栈
- 一个完整案例:从架构设计到代码实现,手把手搭建AI Agent系统
- 一套思维模型:跨平台架构设计的核心原则和决策框架
无论你是Android开发者想拓展技术边界,还是全栈工程师在寻找统一语言方案,这篇文章都值得你细读。让我们开始这段从Android到AI Agent的KMP之旅。
1.1 KMP技术栈的定位与价值
要理解KMP的定位,先回答一个本质问题:跨平台到底跨什么?
业界有三种主流答案。Flutter说“跨UI”,一套Widget渲染所有平台;React Native说“跨交互”,JavaScript桥接原生组件;而KMP说“跨逻辑”——UI交给各平台原生实现,业务逻辑写一次就够了。
这三种思路没有绝对优劣,但KMP的选择在2025年之后显得特别聪明。为什么?因为AI时代的应用复杂度不在UI层,而在业务层。一个AI Agent需要管理对话状态、编排工具调用、处理流式响应——这些全是纯逻辑,跟按钮样式、动画曲线没关系。KMP把这些逻辑写成Kotlin Common模块,Android、iOS、Web、Server直接引用,零额外成本。
这是KMP的第一个核心价值:逻辑共享的精确性。你不必强迫设计师妥协于统一的UI风格,只需要让所有平台用同一套可靠的业务代码。
第二个价值更隐蔽但更重要:类型安全的跨端能力。Kotlin的强类型系统加上序列化框架,让数据模型在不同平台间无缝传递。你定义一次data class Message(val role: String, val content: String),它就能在Android的ViewModel、iOS的ViewController、Web的Compose组件和Ktor服务端之间精准流转。这种确定性在AI Agent场景下是刚需——你不希望一个Agent的推理结果因为平台切换而丢失字段。
第三个价值是人才密度的最大化。一个Kotlin开发者可以同时贡献移动端、服务端和AI Agent模块。这意味着团队知识共享更快、代码审查更精准、轮岗成本更低。对中小团队来说,这种多面手能力比什么都值钱。
当然,KMP不是万能药。UI的跨平台体验目前仍不如Flutter流畅,iOS端的某些原生特性需要额外适配。但从“全栈统一”的视角看,KMP是目前最接近理想的方案。它的定位不是取代谁,而是补上跨平台架构中最缺失的一块——可复用的业务内核。
1.2 文章目标与读者收益
这篇文章不是走马观花的技术科普,而是一次沉浸式的项目复盘。我会按照真实开发的时间线,从需求分析、技术选型、环境搭建,到逐层实现Android端、服务端、AI Agent模块,最后完成多端联调和部署。
在这条路径上,你将获得系统的认知:
- 架构决策的思考过程:为什么选Ktor而不是Spring Boot?为什么用Compose Multiplatform而不是各自原生UI?我当时的权衡逻辑是什么?
- 实际代码的完整呈现:每个关键模块都有可运行的Kotlin代码示例,覆盖Common模块定义、平台适配、Agent编排等核心环节
- 踩坑经验的前置共享:依赖注入在KMP中的注意事项、协程在跨平台中的调度策略、AI流式响应在多端同步的挑战
- 思维框架的内化:学完这篇文章,你带走的不是一句“KMP很好用”,而是一套可以迁移到其他全栈项目的分析框架
特别要说明的是,这篇文章假设你有Kotlin基础、用过Jetpack Compose写Android应用。如果你完全没接触过Kotlin,建议先花一周时间过一遍官方Koans教程,再回来读会更顺畅。对于有Flutter或RN经验的读者,我会在关键节点对比三种方案的差异,帮你建立跨技术栈的全局视角。
准备好了吗?我们先从KMP技术栈的深度解析开始,搭好理论地基。
二、KMP技术栈深度解析
任何技术决策的第一步都应该是“搞清楚它是什么”。KMP的概念虽然不复杂,但它的架构设计和工具生态有一套自己的逻辑。这一节我们把KMP拆开来看,从核心机制到生态工具,再到性能优化的实操策略。
2.1 KMP核心架构与设计哲学
KMP的架构可以从三个层次来理解。
第一层:Common模块——共享逻辑的心脏
这是KMP最核心的概念。Common模块里写的是纯Kotlin代码,不依赖任何平台API。它包含数据模型、业务规则、网络请求的定义、数据库操作的抽象接口——一句话,你能想到的所有“跟UI无关的逻辑”都应该放在这里。
共享业务逻辑层的设计原则很简单:只写逻辑,不写平台实现。比如你定义了一个expect fun getPlatformName(): String,这是期望声明。然后Android模块用actual fun getPlatformName(): String = "Android"实现,iOS模块用actual fun getPlatformName(): String = "iOS"实现。Common模块根本不关心这些细节,它只管在合适的时机调用这个函数。
这种设计有一个精妙的副作用:它迫使你从一开始就做关注点分离。如果一个类里同时混杂了业务计算和SharedPreferences操作,它在KMP架构下根本编译不过。这倒逼团队把代码写得模块化、可测试,对代码质量是正向约束。
第二层:Expect/Actual机制——平台差异的优雅桥梁
Expect/Actual是KMP处理平台差异的核心手段,也是新手最容易踩坑的地方。
简单说,你在Common模块里用expect关键字声明一个“我期望有这个能力”,然后在每个平台模块里用actual给出具体实现。编译器会在链接阶段把声明和实现对上,对不上就报错。
这里有个关键认知:Expect/Actual不是用来绕过跨平台限制的,而是用来给平台差异画边界的。最佳实践是让expect声明的接口尽量抽象、尽量通用,把平台细节封装在actual实现里。比如你不应该暴露expect fun getAndroidContext(): Context,而应该声明expect fun getAppVersion(): String,让Android实现自己去读PackageInfo,iOS实现去读Bundle。
第三层:编译目标矩阵——KMP的真实版图
KMP支持六种编译目标,覆盖了主流的技术场景:
| 编译目标 | 产出物 | 典型场景 |
|---|---|---|
| Android | JVM字节码/AAR | 移动端应用 |
| iOS | Native框架 | 移动端应用 |
| JVM Desktop | JAR/可执行文件 | 桌面应用 |
| JS (Browser) | JavaScript模块 | Web前端 |
| JS (Node.js) | JS模块 | Serverless函数 |
| Linux/macOS Native | 原生可执行文件 | CLI工具、服务端 |
2025年之后,KMP的服务端Native目标成熟度大幅提升,这为KMP真正打通“全栈语言统一”铺平了道路。你现在可以用Kotlin写一个Common模块,然后分别编译为Android库、iOS Framework、Web JS包和Linux原生可执行文件——真正的一次编写,六端运行。
2.2 KMP生态工具链
KMP的生态已经形成了一个完整的技术栈,每个工具解决一个特定层面的问题。
Compose Multiplatform:声明式UI的跨平台方案
这是JetBrains近年最重磅的产品之一。它把Jetpack Compose的声明式UI范式带到了所有平台——Desktop、Web、iOS,都在用同一套@Composable函数写界面。
不同于Flutter的自绘引擎,Compose Multiplatform在Desktop上直接用Skia渲染,在iOS上通过UIKitView桥接,在Web上基于Canvas输出。这种策略让它在各平台上有较接近原生的动画性能和交互体验。2025年Compose Multiplatform for iOS进入稳定版后,其流畅度已经达到生产可用级别。
对Android开发者来说,学习曲线极低——95%的Compose API是跨平台通用的。你只需要注意平台特定的组件差异(比如Android有BackHandler,Desktop没有),其他几乎无缝切换。
Ktor:Kotlin原生网络框架
Ktor是JetBrains官方出品的HTTP框架,定位是“Kotlin-first的网络解决方案”。它最大的特点是异步、协程原生、跨平台。
服务端可以用Ktor Server构建REST API和WebSocket服务,客户端可以用Ktor Client在Android、iOS、Desktop上发网络请求。两者在Common模块里共享同一套数据模型和序列化逻辑,通信一致性天然保证。
Ktor的插件机制也很优雅。认证、CORS、压缩、序列化都需要配置对应的Plugin,每个Plugin独立安装,不会互相污染。对于AI Agent场景,Ktor的流式响应支持和WebSocket能力正好适配大模型的SSE(Server-Sent Events)输出。
SQLDelight:类型安全的数据库访问
SQLDelight不是ORM,而是“SQL生成类型安全Kotlin代码”的工具。你写.sq文件定义SQL查询,编译时自动生成对应的Kotlin数据类和查询函数。
这意味着类型检查发生在编译期而不是运行时。如果你改了表结构但没改对应的查询,编译器会直接报错,不给你留隐患。对于跨平台场景,SQLDelight的另一个优势是驱动适配层清晰——Android用AndroidSqliteDriver,iOS用NativeSqliteDriver,Desktop用JdbcSqliteDriver,查询逻辑完全在Common模块里,零修改。
Kotlinx.serialization:高效的序列化方案
这是Kotlin官方出品的序列化库,支持JSON、Protobuf、CBOR等多种格式。在KMP项目中,序列化是数据流转的命脉——从服务端到客户端、从本地存储到网络传输,数据模型需要频繁序列化和反序列化。
Kotlinx.serialization的核心优势是编译时代码生成,不需要反射,跨平台性能一致。你只需给数据类加上@Serializable注解,剩下的全是编译器的工作。它还天然兼容Kotlin的空安全和非空断言——序列化时不会丢失类型的nullability信息。
2.3 性能与包体积优化策略
KMP项目的优化要从“共享”和“隔离”两个维度来考虑。
代码共享率的衡量与优化
代码共享率 = Common模块代码行数 / 项目总代码行数。理论上共享率越高越好,但实践中80%就已经很理想了。剩下的20%是平台特定代码(UI适配、平台API调用、权限处理),不可能也不应该强制共享。
提高共享率的技巧是不断追问“这段逻辑依赖平台吗”。比如日期格式化,如果只用kotlinx-datetime就能搞定,就别让平台去读系统Locale。加密操作尽量用纯Kotlin实现的库(如Kotlin-crypto),而不是调Android的Cipher或iOS的CryptoKit。每减少一个expect/actual声明,共享率就上升一点,维护成本就下降一截。
资源管理的最佳实践
KMP的资源管理当前还在演进中,但基本原则已清晰:字符串资源放入Common模块的.properties文件,图片等二进制按平台分开放。Compose Multiplatform 1.6之后引入了官方的resource API,支持跨平台访问字符串、图片、字体等资源,大幅简化了资源管理。
对于国际化需求,推荐在Common模块里定义Strings对象,用expect/actual机制让各平台读取本地化资源。这样业务代码始终引用同一个Strings.loginTitle,平台模块负责提供实际的翻译文本。
编译时优化技巧
KMP的编译速度是个老生常谈的问题,尤其在多平台同时编译时。几个实用技巧:
- 增量编译:确保Gradle配置里启用build caching和configuration caching,Kotlin 2.0之后增量编译效果显著提升
- 模块化拆分:不要把Common模块搞成单一巨型模块。按业务域拆成多个小模块(
common:domain、common:network、common:database),让Gradle的并行编译能力发挥出来 - 编译目标精简:只在需要的时候声明编译目标。如果你暂时不做Web,就不要加
js()声明。已经加了的按需注释掉实验性目标的声明 - 缓存远程依赖:在CI环境设置Gradle remote build cache(如使用Gradle Enterprise或自建缓存节点),加速团队所有成员的编译
三、从Android到全栈:技术迁移实战
理论讲完了,现在进入最实用的部分。假设你现在的起点是一个标准的Android项目——用Jetpack Compose写UI、Hilt做依赖注入、Retrofit发网络请求。目标是把这套项目改造成KMP架构,扩展到iOS、Web和Desktop,最后再接入AI Agent。
这条路我走了两次,一次成功,一次失败。失败的那次是因为太激进——试图一次性把所有代码都抽到Common模块,结果编译错误排山倒海,团队集体崩溃。成功后我总结出一个铁律:增量迁移,逐层验证。下面就是这条经过验证的实战路径。
3.1 Android原生项目KMP化改造
改造的第一步不是写代码,而是画边界。打开你现有项目的目录结构,用三种颜色分别标记:
- 绿色:纯业务逻辑(数据验证、计算规则、状态机)——这些是直接迁移到Common模块的
- 黄色:平台封装层(网络请求、数据库访问、文件读写)——这些需要先定义expect接口,再在Android模块里用actual实现
- 红色:纯UI和平台API(Composable函数、Activity、权限请求)——这些留在Android模块不动
举个例子,一个电商App的“优惠券校验逻辑”就是典型的绿色代码。它涉及日期判断、金额计算、使用条件匹配——全是纯逻辑,跟Android系统零关系。直接把这部分Kotlin文件移到commonMain目录下,编译,通过,迁移完成。
依赖注入框架的选择:Koin vs Dagger
这里有一个分叉路口,必须提前做选择。
Dagger/Hilt在Android生态里是主流,但它的核心机制是编译时代码生成,依赖了Android的注解处理器。在KMP场景下,纯Common模块不支持Android注解处理器,导致Dagger无法直接使用(虽然有KSP的KMP支持,但成熟度有限)。
Koin则是运行时注册、纯Kotlin实现,天然跨平台。你可以在Common模块里定义一个commonModule,所有平台的DI容器都从它延伸。缺点是运行时有轻微性能损耗、缺少编译期验证,但换来的是跨平台的统一性。
我的建议是:新KMP项目直接用Koin。如果你现有项目用了Hilt且体量不大,逐步迁移到Koin;如果项目很大,可以考虑维持Android模块的Hilt不变,只在Common模块和新增的KMP模块里使用Koin。两套DI框架在同一个项目里并不冲突。
ViewModel的跨平台适配
这是KMP迁移中最需要动脑的环节。Android ViewModel的核心能力是:ViewModelProvider创建实例、viewModelScope管理协程生命周期。这两个能力在iOS、Desktop上没有直接对应物。
KMP的解决方案是用一个纯Kotlin的ViewModel基类,自己实现生命周期管理。代码如下:
// commonMain 中定义
open class KmpViewModel {
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
val viewModelScope: CoroutineScope get() = scope
fun onCleared() {
scope.cancel()
}
}
// Android 适配
class AndroidKmpViewModel : KmpViewModel(), ViewModel() {
override fun onCleared() {
super.onCleared()
// 触发 KmpViewModel 的资源清理
}
}
Android端让ViewModel同时继承KmpViewModel和Android的ViewModel,这样viewModelScope同时满足两端需求。iOS端直接用KmpViewModel,在ViewController的deinit或viewDidDisappear里调用onCleared()。Desktop端同理,在Compose的DisposableEffect里绑定生命周期。
3.2 服务端开发:KMP on Backend
当Common模块的业务逻辑稳定之后,服务端开发会变得异常顺畅——因为你已经在用同一套数据模型和验证逻辑了。
使用Ktor构建RESTful API
Ktor的API设计很符合Kotlin风格:
fun Application.module() {
install(ContentNegotiation) { json() }
install(CORS) { anyHost() }
routing {
route("/api/v1") {
get("/health") {
call.respond(mapOf("status" to "ok"))
}
post("/chat") {
val request = call.receive<ChatRequest>()
val response = chatService.process(request)
call.respond(response)
}
}
}
}
关键点在于ChatRequest和ChatResponse都来自Common模块。Android端发请求时用同一套数据类,服务端收到后直接处理。不需要写Java/Kotlin ↔ JSON的转换代码,序列化完全自动化。
数据库访问层设计
对于大多数业务场景,SQLDelight + PostgreSQL/MySQL的组合已经足够了。连接池用HikariCP(JVM环境)或内置连接管理(Native环境)。数据库迁移用Flyway或Liquibase,在应用启动时自动执行。
一个典型的数据库访问层结构:
commonMain/
└── database/
├── UserQueries.sq // SQL定义
├── Database.kt // expect声明
androidMain/
└── database/
└── Database.android.kt // actual实现(AndroidSqliteDriver)
serverMain/
└── database/
└── Database.server.kt // actual实现(JdbcSqliteDriver/PostgreSQL)
查询定义在Common模块,驱动实现在各平台。如果你用的是标准SQL(不依赖特定数据库方言),这层共享率可以达到100%。
身份认证与授权实现
认证层推荐JWT方案。Common模块定义AuthService接口和JWT解析逻辑(可以用纯Kotlin的com.auth0:java-jwt库),各平台模块处理具体的Token存储(Android用EncryptedSharedPreferences,服务端用Redis,Web用localStorage)。
权限控制用注解+拦截器模式。在Ktor里注册一个AuthenticationPlugin,读取请求头中的Bearer Token,解析出用户角色,再跟路由的@RequiredRole("admin")注解对比。这个逻辑完全可以写在Common模块里,Ktor的多平台特性保证它在JVM Server和Native Server上都能工作。
3.3 Web前端:Compose for Web
Compose for Web目前有两种模式:DOM模式和Canvas模式。
DOM模式把Compose节点映射为HTML DOM元素,适合内容型网站(博客、文档站、后台管理)。Canvas模式用Skia直接在Canvas上绘制,效果接近Desktop应用,适合交互密集型场景。
对于大多数全栈KMP项目,DOM模式是更务实的选择。它能正常使用浏览器的自动翻译、无障碍访问、搜索引擎索引功能,SEO友好度远超Canvas模式。同时DOM模式的文件体积更小(因为不用打包Skia引擎),首屏加载速度也更快。
声明式Web UI开发
如果你用过Jetpack Compose,Compose for Web的体验几乎是0学习成本:
@Composable
fun ChatPage(viewModel: ChatViewModel) {
Column(
modifier = Modifier.fillMaxSize().padding(16.px),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("智能客服", style = MaterialTheme.typography.h4)
Spacer(Modifier.height(16.px))
LazyColumn(modifier = Modifier.weight(1f)) {
items(viewModel.messages) { msg ->
MessageBubble(msg)
}
}
InputBar(
onSend = { text -> viewModel.sendMessage(text) }
)
}
}
这里的ChatViewModel就是前面提到的KmpViewModel,它在Android端和Web端用完全相同的代码驱动UI更新。LazyColumn、Text、Button等组件是Compose Multiplatform通用的,不需要额外学习Web的div/span/CSS结构。
状态管理与路由设计
状态管理推荐用Compose内置的mutableStateOf + StateFlow模式。路由可以用Compose Navigation或社区的Voyager库。鉴于Voyager已支持KMP,推荐用它来处理多平台的Screen管理和参数传递。
注意一点:Web端的“返回按钮”行为需要特殊处理。浏览器的back操作触发的是popstate事件,你在Compose for Web里需要用BackHandler(跨平台Compose组件)来拦截这个事件并同步路由状态。
与后端API的集成
Web端用Ktor Client发请求,跟Android端完全一样。一个常见的模式是在Common模块定义ApiClient接口,各平台提供HTTP引擎的实现(Android用OkHttp,Web用Fetch,Desktop用CIO)。
需要特别注意的是CORS配置。Ktor服务端要显式添加install(CORS)并配置允许的源(origin),否则Web端的请求会被浏览器直接拦截。开发环境通常配置anyHost(),生产环境务必改成具体的域名白名单。
3.4 桌面应用:Compose Desktop
Desktop是KMP支持最成熟的非Android平台。Compose Desktop用Skia做渲染引擎,打包成原生可执行文件(macOS的.dmg、Windows的.exe或.msi、Linux的.deb),用户体验接近原生应用。
原生桌面应用开发
Desktop应用的结构跟Android应用高度相似:
fun main() = application {
Window(
onCloseRequest = ::exitApplication,
title = "智能客服管理端",
state = rememberWindowState(width = 1200.dp, height = 800.dp)
) {
MaterialTheme {
App(viewModel = AdminViewModel())
}
}
}
你可以复用Android端90%的Compose UI代码。LazyColumn在Desktop上支持键盘导航和鼠标滚轮,TextField支持Ctrl+C/V等系统快捷键。文件选择对话框用java.awt.FileDialog或社区封装的Compose拓展,托盘图标用AWT API。
系统集成与本地化
Desktop端的独特能力是访问本地文件系统、系统剪贴板、系统通知。这些能力通过expect/actual机制暴露给Common模块:
// commonMain
expect class FilePicker {
suspend fun pickFile(): FileContent?
}
// desktopMain
actual class FilePicker {
actual suspend fun pickFile(): FileContent? {
return withContext(Dispatchers.IO) {
val dialog = FileDialog(null as Frame?, "选择文件", FileDialog.LOAD)
dialog.isVisible = true
if (dialog.file != null) {
FileContent(dialog.file.readBytes(), dialog.file.name)
} else null
}
}
}
本地化方面,Compose Desktop支持读取系统语言设置,配以资源文件的多语言方案即可实现i18n。
打包与分发策略
JetBrains提供了Compose Desktop的Gradle插件,一行配置就能打包:
compose.desktop {
application {
mainClass = "com.example.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "SmartCS"
packageVersion = "1.0.0"
macOS { bundleID = "com.example.smartcs" }
windows { menuGroup = "SmartCS" }
linux { packageName = "smartcs" }
}
}
}
打包产物是独立的可执行文件,用户不需要安装JDK。macOS上会生成.dmg镜像,Windows上生成.msi安装包,Linux上生成.deb包。应用启动时JRE由JetBrains Runtime提供,这是JetBrains维护的OpenJDK发行版,对Compose Desktop做了针对性优化。
四、AI Agent时代的KMP架构
前面三章搭建了一个完整的KMP全栈骨架。现在我们要给这个骨架注入灵魂——AI Agent。
2024年下半年以来,AI Agent从概念走向落地。LangChain、AutoGPT、CrewAI等框架让构建智能体变得前所未有的简单。但一个尴尬的现实是:这些框架几乎全是Python生态的。如果你用KMP做全栈,AI模块要不要单独写一套Python服务?
我们的答案是:不。KMP完全可以承载AI Agent的核心逻辑——从LLM调用到工具编排,从对话管理到向量检索,全部Kotlin化。下面我会展示这是怎么做到了,以及为什么这样做比Python方案更有架构优势。
4.1 AI Agent技术栈概览
先界定概念。AI Agent是一个能够自主感知环境、制定计划、执行工具、评估结果的智能体系统。它的核心组件包括:
大语言模型(LLM)集成模式
这是Agent的大脑。LLM集成有三种模式:
- 直接API调用:通过HTTP请求调用OpenAI/Claude/通义千问等模型的REST API。这是最灵活的方式,但需要自己管理重试、限流、流式响应
- 框架封装:通过LangChain4J/LangChain4K这类框架统一调用不同的LLM,一个接口切换模型厂商
- 本地部署:用llama.cpp或vLLM部署开源模型,通过本地API调用,适合对数据隐私有高要求的场景
KMP全栈在这三种模式上都能工作。Common模块定义LlmClient接口,各平台的actual实现可以用Ktor Client发HTTP请求(云端API),也可以调JNI/Native接口(本地模型)。
智能体(Agent)架构设计
Agent的核心工作流是循环:接收用户输入 → 调用LLM推理 → 判断是否需要使用工具 → 执行工具 → 把结果反馈给LLM → 生成最终回复。这个循环通常由Agent引擎驱动,代码量不大但状态管理很复杂。
一个好的Agent架构应该具备:
- 工具可插拔:添加新工具不需要修改核心引擎
- 记忆可扩展:支持短期记忆(当前会话)和长期记忆(向量数据库)
- 推理可观测:每一步的思考过程都要记录下来,方便调试和审计
工具调用(Tool Calling)机制
工具是Agent的“手”。一个工具就是一个函数,接收参数、返回结果。LLM决定“用哪个工具”和“传什么参数”,Agent引擎负责执行这个函数并把结果返回给LLM。
比如一个“天气查询”工具的定义:
data class WeatherTool : AgentTool {
override val name = "get_weather"
override val description = "查询指定城市的实时天气"
override val parameters = listOf(
ToolParameter("city", "string", "城市名称,如'北京'")
)
override suspend fun execute(args: Map<String, Any>): ToolResult {
val city = args["city"] as String
val weather = weatherService.query(city) // 这是Common模块里已经有的服务
return ToolResult.Success(weather.toJson())
}
}
关键观察:weatherService.query()在KMP架构里本来就存在——这是之前的全栈工程里已经写好的业务逻辑。在AI Agent里,工具调用只是给现有业务函数加了一层参数描述壳,让LLM知道“可以这样调用它”。这正是KMP统一技术栈的巨大红利——业务能力天然可被Agent调用,不需要额外包装RPC或跨语言桥接。
4.2 KMP在AI Agent中的角色定位
KMP在AI Agent里扮演三个关键角色,每一个都让架构变得更简洁。
统一的业务逻辑层
这是最核心的定位。一个AI Agent不只是“调LLM聊天”——它的真正价值在于调用业务系统来完成任务。比如智能客服Agent需要查询订单、修改地址、计算退款金额。这些业务逻辑在KMP架构下已经以Common模块的形式存在,跨平台可用。
Agent工具调用直接访问Common模块的服务层,不需要HTTP调用微服务,不需要处理网络延迟和序列化开销。对Agent引擎来说,工具就是一个本地函数调用,毫秒级响应。这对需要调用10+个工具的复杂Agent场景来说,性能优势非常显著。
多平台AI交互界面
Agent的对话界面需要部署到多个终端。用户可能在手机App上跟Agent聊天,可能在网页上操作,可能在桌面管理端查看Agent的推理日志。
用KMP + Compose Multiplatform,一套对话UI代码覆盖所有平台。ChatBubble组件、StreamingText组件、ThinkingIndicator组件——写一次,在Android/iOS/Web/Desktop上渲染。当Agent产品需要在更多设备触达用户时,UI层的边际成本趋近于零。
数据同步与状态管理
Agent涉及多种状态:对话历史、用户偏好、工具执行缓存、向量索引。这些状态需要跨会话持久化、跨设备同步。KMP的数据库抽象层(SQLDelight)+ Ktor服务端让状态同步变得非常自然——所有读写操作都走Common模块定义好的接口,序列化自动完成。
举个例子:用户在手机上跟Agent聊了一半,打开桌面端继续。会话历史的恢复逻辑在Common模块里定义,Android端和Desktop端只是调用同一个SessionManager.restore(sessionId)方法,数据持久层会自动从本地数据库或远程服务端拉取。
4.3 LangChain与KMP的集成
LangChain是AI Agent开发的事实标准框架,但它主要面向Python/JavaScript生态。在Kotlin生态里,我们有两个选择:LangChain4J(Java生态,Kotlin可调用)和LangChain4K(Kotlin原生,目前还在早期阶段)。
LangChain4K的Kotlin支持
我个人的选择是LangChain4K。虽然它比LangChain4J年轻,但API设计更符合Kotlin习惯,对协程和Flow的支持也更原生。
一个基本的Agent定义:
val agent = Agent {
model = OpenAiModel(
apiKey = config.openAiKey,
modelName = "gpt-4o"
)
tools += WeatherTool()
tools += OrderQueryTool()
systemPrompt = "你是智能客服助手,可以查询天气和处理订单问题。"
}
val response = agent.invoke("北京今天天气怎么样?")
agent.invoke()返回的是一个Flow<AgentStep>,每一步推理和工具调用都会实时emit出来。前端拿到这个Flow后,可以展示“正在思考… → 正在调用天气查询工具… → 正在组织回复…”的实时过程,用户体验非常好。
智能体工作流的KMP实现
KMP的一大优势是让Agent工作流在客户端和服务端复用。考虑这个场景:
- 服务端Agent:处理复杂查询,调用敏感API(如支付接口),执行长耗时任务
- 客户端Agent:处理简单对话,做本地意图分类,在脱机状态下提供基础服务
两个Agent共享同一套工具定义和推理逻辑(Common模块),但部署位置不同。服务端Agent在Ktor应用里运行,客户端Agent在Android App或Desktop应用里运行。这种灵活度是Python方案很难实现的——你不可能把Python Agent打包进Android APK,但在KMP里这完全是自然延伸。
向量数据库的跨平台访问
RAG(检索增强生成)是AI Agent的标配能力。它需要向量数据库来存储和检索知识文档。KMP在这个领域的选择包括:
- Qdrant + REST API:通过HTTP调Qdrant服务,客户端和服务端都能用
- ChromaDB Kotlin SDK:社区库,适合小规模本地使用
- SQLite + 向量拓展:SQLDelight管理结构化数据,额外的向量表自己维护
我个人推荐Qdrant方案:它在服务端自建部署,客户端通过HTTP访问。Common模块里定义一个VectorStore抽象接口,Ktor Client做具体实现。这样一来,知识库的写入(文档入库)和检索(相似查询)都走统一通道,Android端和Web端体验一致。
五、实战案例:智能客服AI Agent全栈系统
前面四章是理论和方法论,现在进入最硬核的部分——代码实战。我们以智能客服系统为例,从系统架构设计、核心代码实现、到部署方案,给出一个完整的KMP全栈AI Agent项目。
这个系统的需求是这样的:用户可以文字或语音咨询订单状态、查询物流、申请退款、修改地址。系统要能理解自然语言,调用真实业务数据,在必要时转接人工客服。前端覆盖Android、Web、Desktop三个终端,服务端用Ktor,AI模块集成到KMP架构内。
5.1 系统架构设计
在讲代码之前,先把架构图画清楚。这决定了后续所有模块的边界和通信方式。
这个架构的关键设计决策:
-
AI Agent引擎放在服务端:因为Agent需要调用LLM API(通常需要API Key不能暴露到客户端)、访问向量数据库、执行敏感业务操作。但Agent的工具接口和推理逻辑定义在Common模块,理论上也能编译到客户端做离线Agent。
-
WebSocket做实时通道:Agent的流式响应通过WebSocket推送给前端,而不是让客户端轮询HTTP。Ktor对WebSocket有原生支持,Common模块里定义的
AgentStreamMessage数据类可以在服务端和客户端之间直接序列化传输。 -
Redis做状态外存:对话状态、Agent中间步骤、限流计数器都放在Redis里。KMP Common模块通过Ktor Client的Redis适配器访问Redis,抽象层让数据读写逻辑跨模块复用。
-
三层解耦:前端只关心展示和交互,业务服务层只关心业务逻辑,AI引擎只关心推理和工具编排。三层之间通过KMP Common模块定义好的数据模型通信,修改任一层不影响其他层。
5.2 核心模块实现
对话管理模块:基于Flow的状态管理
这是整个系统的中枢。对话管理模块负责维护一次对话的完整生命周期:
// commonMain - 对话状态定义
data class ConversationState(
val sessionId: String,
val messages: List<ChatMessage> = emptyList(),
val agentSteps: List<AgentStep> = emptyList(),
val isThinking: Boolean = false,
val currentToolCall: String? = null
)
class ConversationManager(
private val agentEngine: AgentEngine,
private val sessionStore: SessionStore
) {
private val _state = MutableStateFlow(ConversationState(sessionId = generateId()))
val state: StateFlow<ConversationState> = _state.asStateFlow()
suspend fun sendMessage(userInput: String) {
// 1. 添加用户消息
_state.update { it.copy(
messages = it.messages + ChatMessage(role = "user", content = userInput),
isThinking = true
)}
// 2. Agent推理(流式)
agentEngine.invoke(userInput, _state.value.sessionId)
.collect { step ->
when (step) {
is AgentStep.Thinking -> _state.update { it.copy(
agentSteps = it.agentSteps + step,
currentToolCall = null
)}
is AgentStep.ToolCalling -> _state.update { it.copy(
currentToolCall = step.toolName
)}
is AgentStep.ToolResult -> _state.update { it.copy(
currentToolCall = null
)}
is AgentStep.FinalAnswer -> {
_state.update { it.copy(
messages = it.messages + ChatMessage(role = "assistant", content = step.content),
isThinking = false,
agentSteps = emptyList()
)}
}
}
}
}
}
前端只需要订阅conversationManager.state这个Flow,Compose会自动触发UI重组。Android/Web/Desktop三端的UI代码几乎一样,区别只在布局适配。
工具调用模块:插件化工具系统设计
工具系统的设计目标是:添加新工具 = 新增一个类文件,不改核心引擎代码。
// commonMain - 工具接口定义
interface AgentTool {
val name: String // LLM看到的工具名
val description: String // LLM看到的描述
val parameters: List<ToolParameter> // LLM看到的参数schema
val requiresConfirmation: Boolean get() = false // 是否需要用户确认
suspend fun execute(args: Map<String, Any>, context: ToolContext): ToolResult
}
// 示例:订单查询工具
class OrderQueryTool(
private val orderService: OrderService // 已在Common模块定义好的服务
) : AgentTool {
override val name = "query_order"
override val description = "根据订单号查询订单的详细状态、物流信息和金额"
override val parameters = listOf(
ToolParameter("orderId", "string", "订单号,格式为 ORD-xxxxxx")
)
override suspend fun execute(args: Map<String, Any>, context: ToolContext): ToolResult {
val orderId = args["orderId"] as? String
?: return ToolResult.Error("缺少订单号参数")
val order = orderService.findByOrderId(orderId)
?: return ToolResult.Error("未找到订单:$orderId")
return ToolResult.Success(order.toSummaryJson())
}
}
工具注册也很简单,DI容器里一条配置搞定:
// 在 Koin 模块中注册所有工具
val toolModule = module {
single<AgentTool> { OrderQueryTool(get()) }
single<AgentTool> { LogisticsTool(get()) }
single<AgentTool> { RefundTool(get()) }
single<AgentTool> { AddressModifyTool(get()) }
}
// Agent引擎启动时自动发现所有AgentTool实例
class AgentEngine(private val tools: Set<AgentTool>) { ... }
多模态支持:文本、语音、图像的统一处理
对于多模态输入(用户发图片、发语音),Common模块定义统一的MultimodalInput:
sealed class MultimodalInput {
data class Text(val content: String) : MultimodalInput()
data class Image(val base64Data: String, val mimeType: String) : MultimodalInput()
data class Audio(val rawData: ByteArray, val durationSeconds: Float) : MultimodalInput()
}
语音转文字调用的是平台特定的语音识别API(Android用SpeechRecognizer,Web用Web Speech API),但转换后的Text统一交给Agent处理。图片的理解由多模态LLM(如GPT-4V)完成,Ktor Client发送base64图片数据,流式返回理解结果。这些处理逻辑封装在PlatformUtil的expect/actual实现里,Common层只看到文本输入输出。
5.3 部署与运维
多平台应用的CI/CD流水线
KMP多平台项目最痛苦的不是开发,而是CI/CD。因为一次提交需要编译Android、iOS、Web、Desktop、Server五个目标,流水线设计不当的话编译一轮要40分钟以上。
推荐的CI架构是矩阵构建 + 增量编译:
# GitHub Actions 示例
jobs:
build-matrix:
strategy:
matrix:
target: [android, ios, desktop, web, server]
runs-on: ${{ matrix.target == 'ios' && 'macos-latest' || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { java-version: '17' }
- uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- run: ./gradlew :composeApp:compileKotlin${{ matrix.target }}
五个目标并行编译,配合Gradle Build Cache,全量编译控制在12分钟以内,增量编译在3分钟以内。iOS目标必须在macOS Runner上跑,其他目标Linux Runner即可。
监控与日志收集
生产环境的监控分三个维度:
- 应用级:Ktor服务端暴露
/metrics端点(Prometheus格式),记录请求量、响应时间、错误率、Agent工具调用成功率 - AI Agent级:每次Agent推理记录完整链路(用户输入→LLM推理→工具调用→最终输出),结构化存入日志系统
- 基础设施级:PostgreSQL慢查询、Redis命中率、Qdrant索引大小,通过Grafana Dashboard统一展示
所有监控埋点代码放在Common模块,用expect/actual适配不同平台的MetricRegistry实现(JVM用Micrometer,Native用Atomix等)。
性能调优与故障排查
AI Agent系统最棘手的性能问题是LLM调用耗时。一次GPT-4的API调用可能需要2-5秒,如果Agent一个回合调用3次工具(每次都需要LLM推理),用户体验的等待时间可能超过15秒。
优化策略:
- 流式响应杜绝等待:LLM每生成一个token就推送给前端,让用户感知到“正在处理”而不是“卡住了”
- 工具调用并行化:如果LLM同时决定调用两个工具(如“查订单状态”和“查物流信息”),Agent引擎并行执行这两个调用,而不是串行等待
- 分级模型策略:简单意图分类用轻量模型(GPT-4o-mini,<500ms),复杂推理再用GPT-4o。一年能省下可观的API费用
- 缓存热点回答:对于频繁出现的FAQ(如“退货流程是什么”),直接把回答缓存到Redis里,命中后跳过LLM调用
故障排查的核心原则是:每一步都要有可追溯的日志。Agent为什么调用这个工具?LLM返回的JSON为什么解析失败?用户为什么被重复扣款?——每条记录都能在日志系统里找到完整的上下文。建议采用OpenTelemetry标准,所有Agent操作的Span自动上报到Jaeger,方便分布式追踪。
六、性能优化与最佳实践
KMP项目进入生产环境后,性能优化和团队规范就是决定长期维护成本的关键。这一节不展开具体代码,而是给出经过验证的策略和检查清单。
6.1 编译时优化
KMP的编译性能是一个持续改善的领域。Kotlin 2.0引入的K2编译器带来了约40%的编译速度提升,但多平台配置仍需精细调校。
增量编译配置:确保根build.gradle.kts中开启kotlin.incremental.useClasspathSnapshot=true。这个参数让Gradle在判断哪些代码需要重新编译时更精确,避免不必要的全量编译。模块间依赖声明越精确,增量编译效果越好——不要用一个common:shared模块把所有东西都包进去。
缓存策略优化:Gradle Build Cache是CI速度的分水岭。团队里第一个人的编译产物被上传到Remote Build Cache,第二个人的编译直接复用缓存,速度差距是数倍甚至数十倍。关键配置是gradle.properties中的org.gradle.caching=true和CI Runner的缓存路径持久化。
资源压缩与混淆:Android模块的R8/ProGuard混淆照常使用。对于Desktop目标,可以用ProGuard的独立版做JAR缩减。Web目标用Kotlin/JS的-Xir-produce-dce选项做死代码消除。Common模块不需要混淆,因为平台模块打包时自然会处理。
6.2 运行时性能
跨平台应用最怕的就是“在一台设备上流畅,另一台上掉帧”。
内存管理最佳实践:协程的SupervisorJob比Job更适合UI层——一个子协程异常不会导致整个scope取消。对于大数据列表,使用LazyColumn的key参数避免不必要的重组。在Compose中,remember和derivedStateOf的合理使用能减少50%以上的重组次数。
协程的合理使用:不要滥用GlobalScope,它的生命周期不受管理。在KMP ViewModel中使用自定义的viewModelScope,在Compose中使用rememberCoroutineScope。耗时操作切换到Dispatchers.IO(JVM)或Dispatchers.Default(Common),UI更新回到Dispatchers.Main。Kotlin 2.0的新的Dispatcher性能有明显提升,建议升级使用。
网络请求优化:Ktor Client默认复用连接池,不需要额外配置。对于高频API(如Agent的工具调用),考虑使用HTTP/2多路复用,减少连接建立开销。大文件上传/下载使用分块传输,配合Flow处理流式数据。
6.3 团队协作规范
KMP项目团队通常混合了Android、iOS、后端背景的开发者,需要明确的协作规范。
代码组织与模块划分:推荐按功能域拆分模块,而不是按层级:
project/
├── common:core/ # 基础工具类、扩展函数
├── common:domain/ # 业务实体、Repository接口
├── common:network/ # API定义、Ktor Client配置
├── common:database/ # SQLDelight查询定义
├── common:ai/ # Agent引擎、工具接口
├── androidApp/ # Android特定代码
├── iosApp/ # iOS特定代码(Kotlin编译)
├── desktopApp/ # Desktop特定代码
├── webApp/ # Web特定代码
└── server/ # Ktor服务端
模块间依赖关系清晰:androidApp依赖common:network,server也依赖common:network,但common:network不依赖任何App模块。谁向上依赖谁,依赖关系严格单向。
测试策略:KMP项目的测试分层:
- 单元测试:写在
commonTest目录,对所有Common模块的纯逻辑做测试(业务规则、数据转换、工具函数)。kotlin.test框架跨平台可用,不需要JUnit - 集成测试:数据库操作、网络请求、Agent工具执行——这些需要实际运行环境。Android用
androidTest,服务端用JUnit + Testcontainers启动PostgreSQL/Redis容器 - UI测试:Compose UI的截图测试用
Compose Preview Screenshot Testing(实验性),端到端测试用Appium(移动端)或Playwright(Web端)
文档与知识管理:KMP项目的文档要点:
README.md中必须包含各模块的编译目标和开发环境说明architecture.md用Mermaid画系统架构图和模块依赖图,每次大重构同步更新- Expect/Actual声明集中的模块,在
actual对应目录放一个README.md解释平台实现细节 - AI Agent的工具清单维护在
docs/tools.md里,每次新增工具同步更新文档
七、未来展望与挑战
写完这篇长文时,KMP生态还在以惊人的速度演进。我认为如下几个趋势将决定KMP的未来。
7.1 KMP技术发展趋势
Compose Multiplatform的成熟度提升:iOS端的Compose Multiplatform已经处于Beta向稳定版过渡的阶段。一旦正式GA,KMP在UI跨平台这个最后短板上将补齐。届时KMP + Compose Multiplatform的组合将直接对标Flutter的全平台方案,且比Flutter多了服务端Native的优点。
工具链的进一步完善:JetBrains在Fleet IDE中深度集成了KMP支持,包括跨平台重构、Expect/Actual导航、多平台调试。Gradle插件也在不断优化编译速度。预计2026年底,KMP的开发体验将接近单平台开发的流畅度。
社区生态的壮大:KMP的第三方库正在快速增长。Coil(图片加载)已支持KMP,Apollo GraphQL已发布KMP版本,甚至Firebase也开始提供官方KMP SDK。这意味着一两年前“没库可用”的痛点正在快速消失。
7.2 AI Agent技术的演进
多模态AI的集成:GPT-4V和Gemini Pro Vision开启了多模态Agent的纪元。未来的Agent不仅能看懂文字,还能理解图片、图表、甚至视频。KMP的强类型系统在处理复杂的多模态数据结构时有天然优势。虽然前端的多模态输入捕获仍需平台特定实现,但处理逻辑可以统一在Common模块。
自主智能体的发展:从“用户问一句、Agent答一句”到“给定一个目标,Agent自主规划多步操作”,这是Agent的下一个阶段。KMP的协程和Flow模型天然适合处理这种长时间运行的自主任务。Agent在后台持续执行,状态变更实时推送给多个终端的UI。
边缘计算与KMP的结合:小模型的崛起(Phi-3、Gemma 2)让在设备端运行Agent成为可能。Android/iOS端的Agent不用联网就能处理大部分简单任务,只有复杂查询才上云。KMP的Common模块可以无痛部署到服务端和客户端,正好匹配这种云边协同架构。
7.3 开发者学习路径建议
对于想掌握KMP全栈 + AI Agent的开发者,建议的学习路径:
第一步:Kotlin语言深度掌握(2-4周)
- 协程与Flow是重中之重——90%的KMP代码依赖它们
- 熟悉
kotlinx.serialization和@Serializable的用法 - 理解
expect/actual机制的语义和设计约束
第二步:跨平台架构设计思维(4-8周)
- 从一个简单Android项目的KMP化改造练手
- 体会“什么逻辑值得共享、什么应该留给平台”的判断力
- 逐步扩展Compose UI到Desktop和Web
第三步:AI相关技术的学习曲线(持续)
- 先理解LLM的基本原理(不需要深入数学,但要懂Token、Embedding、Context Window的概念)
- 用LangChain或类似的框架亲手搭建一个Agent Demo
- 然后把KMP Full Stack和Agent Demo整合——这就是本文展示的完整链路
八、总结
走完这条从Android到AI Agent的KMP全栈之路,我们一起来回顾一路的风景。
8.1 核心价值回顾
这篇文章试图传达三个核心认知:
KMP实现真正的一次编写,多端运行。不是“写一次调半天”,而是通过精确的架构设计,让80%的代码在六个平台上零修改编译。这80%恰好是你应用的核心价值——业务逻辑、数据处理、AI推理。剩下的20% UI适配和平台特性,没有框架能帮你省掉。
全栈开发效率的显著提升。数据和逻辑的统一节省了重复开发时间,类型安全消除了平台间的隐性bug,统一语言降低了团队沟通成本。综合效率提升大概在40%-60%之间——这是我两个项目实测的结论。
在AI时代的技术竞争力。AI Agent需要的不是某个语言或框架,而是“可调用的业务能力”。KMP用一套代码把业务能力同时暴露给Web、移动端和AI引擎,这种架构上的灵活性是技术栈碎片化的团队难以复制的。
8.2 行动建议
阅读这篇文章的你,可能处在不同的阶段。我对三种读者分别给出建议:
如果你现在是Android开发者:下一周就开始试试。开一个新分支,把你项目里一个数据Validation类移到commonMain目录下,让它在Android和Desktop上都能编译。这个微小的成功会打开一扇新的大门。
如果你是技术团队负责人:评估一下你们的现状。业务逻辑频繁跨端修改吗?Android和iOS各维护一套相似的Repository代码吗?产品有计划扩展到Web或Desktop吗?如果两个以上的答案是“是”,KMP值得认真考虑。
如果你在做AI产品:对比一下“Python后端 + 各端独立前端”和“KMP统一前后端 + Agent引擎”这两种架构的总开发成本。你会发现后者在多人团队、多终端场景下的优势非常明显。
最后,技术永远在变,但架构思维是长久的。这篇文章教的不只是KMP怎么用,更希望传递的是一种架构哲学:用尽可能统一的语言,消除尽可能多的重复,让每一行代码的价值最大化。当你的Android代码能直接驱动AI Agent的推理引擎时,你就真正理解了这句话。
KMP的全栈故事还在继续,AI Agent的演进也才刚刚开始。现在入场,时机正好。
附录
A. 推荐学习资源
- 官方资源:Kotlin Multiplatform官方文档、Compose Multiplatform官方示例(JetBrains GitHub)
- 社区项目:PeopleInSpace(KMP + Compose Multiplatform明星项目)、KMP-Awesome(社区维护的资源合集)
- 技术会议:KotlinConf年度大会、Droidcon各城市站点的KMP专场
- 书籍:《Kotlin Multiplatform by Tutorials》(Ray Wenderlich出品)、《Kotlin Design Patterns and Best Practices》
B. 常见问题解答(FAQ)
Q: KMP与Flutter/React Native的主要区别是什么?
A: KMP共享的是业务逻辑层,UI可以是原生也可以是Compose;Flutter/RN共享的是UI层,用统一渲染引擎。这种区别导致KMP在UI一致性上不如Flutter,但逻辑共享的深度和灵活性更强。如果追求“完全一致的UI体验”,选Flutter;如果追求“业务逻辑跨端复用 + 灵活UI”,选KMP。
Q: KMP项目的性能瓶颈通常在哪里?
A: 编译速度是工程瓶颈,用Build Cache和模块拆分解决;协程调度是运行时瓶颈,避免频繁的Dispatcher切换;LLM调用是AI Agent的性能瓶颈,用流式响应、并行工具调用、分级模型策略来缓解。
Q: 现有项目迁移KMP有什么风险?
A: 渐进迁移可以控制风险——先迁移一个独立模块验证可行性,再逐步扩大范围。最大的挑战其实是团队的学习意愿,而不是技术本身的复杂度。如果团队有较强的Android开发能力,学习曲线其实很平缓。
C. 工具与库推荐
- 开发工具:IntelliJ IDEA Ultimate(KMP最佳IDE)、Fleet(JetBrains新一代轻量编辑器,KMP支持在快速完善)、Android Studio(Android目标调试)
- 监控与调试:Grafana + Prometheus(服务端监控)、Sentry(错误追踪,支持KMP)、Jaeger(分布式追踪,Agent调用链可视化)
- 第三方库生态:Koin(依赖注入)、Voyager(多平台导航)、Kamel(跨平台图片加载)、Apollo GraphQL KMP(声明式网络请求)、Kotlinx-datetime(跨平台日期时间处理)
更多推荐



所有评论(0)