基于 CMP(Compose Multiplatform)共享 UI + SQLDelight + Voyager 的落地样例,以下从架构、数据层、导航与跨端适配四个维度,拆解一套 Kotlin 代码同时驱动 Android/iOS AI 对话客户端的实战路径。
一、整体架构与代码复用率
CMP 允许用同一份 Kotlin + Compose 代码编译至 Android、iOS、Desktop 等端,业务逻辑(网络、ViewModel、DB)可 100% 共享,UI 代码共享率普遍在95%+
。典型分层为:
- 共享层(commonMain):API 客户端、ViewModel、本地库、导航图
- 平台入口:Android 用
ComponentActivity.setContent,iOS 用ComposeUIViewController包装后由 SwiftUI 调用
二、数据持久化:SQLDelight 落地
在跨端 AI 客户端(如 DeepCo)中,SQLDelight 作为类型安全本地库,在commonMain定义Conversation、Message、ApiEndpoint等表,自动生成 SQL 查询,统一存储聊天记录与密钥
。Chatter 同样采用 SQLDelight 做 SQLite 持久化,保障 Android/iOS/Desktop 对话历史离线可用。
三、导航与路由:Voyager 角色补充
虽然搜索结果未直接展开 Voyager 代码,但同生态的导航实践显示:CMP 项目常用声明式导航库(如 JetBrains Navigation Compose 或第三方 Voyager)管理聊天页/设置页跳转
。Voyager 以纯 Kotlin 多平台路由替代平台原生导航,使commonMain持有全量页面栈,Android/iOS 仅渲染。
四、跨端 AI 对话关键代码范式
- 共享聊天界面(commonMain)
kotlin
@Composable fun ChatScreen(presenter: AIPresenter) { val state by presenter.state.collectAsState() LazyColumn { items(state.messages) { MsgBubble(it) } } TextField(onValueChange = { presenter.ask(it) }) }- Android 入口
kotlin
class MainActivity : ComponentActivity() { override fun onCreate(s: Bundle?) { setContent { ChatScreen(AIPresenter()) } } }- iOS 入口
kotlin
fun MainViewController() = ComposeUIViewController { ChatScreen(AIPresenter()) }Swift 侧用UIViewControllerRepresentable嵌入,实现“一套 UI 代码双端运行”
。
五、痛点直击与避坑
- API 密钥安全:密钥存本地(DataStore/Room/SQLDelight),不硬编码,BYOK 模式优先
- 流式响应:Ktor 协程处理 SSE,Android/iOS 共用
bodyAsChannel()解析data:增量 - 平台差异:文件选择等用
expect/actual隔离,公共 UI 无感知
综上,CMP + SQLDelight + Voyager 的组合让 Android/iOS AI 对话应用从“双代码库”收敛为“单 KMP 模块”,显著降低维护成本并保持一致体验。