KMP全栈开发:从Android到AI Agent的技术演进与实践
·
一、 引言:KMP的崛起与全栈愿景
Kotlin Multiplatform (KMP) 作为 JetBrains 推出的跨平台解决方案,正从移动端(Android/iOS)向更广阔的全栈领域演进。本文将探讨如何利用 KMP 构建从移动端到服务端,乃至新兴 AI Agent 应用的全栈技术体系。
二、 KMP 技术核心与生态现状
- 共享业务逻辑: 使用 Kotlin 编写一次,在 JVM、Native、JS 等多平台运行。
- 平台特定实现: 通过 expect/actual 机制处理平台差异。
- 成熟度与工具链: Compose Multiplatform、Ktor、SQLDelight 等生态工具。
三、 第一站:巩固 Android 与 iOS 移动端
- 架构模式: 在共享模块中实现 MVVM/MVI 的 ViewModel 与 UseCase。
// 共享模块中的 ViewModel 示例
class TaskViewModel(private val taskRepository: TaskRepository) : ViewModel() {
private val _tasks = MutableStateFlow<List<Task>>(emptyList())
val tasks: StateFlow<List<Task>> = _tasks.asStateFlow()
fun loadTasks() {
viewModelScope.launch {
_tasks.value = taskRepository.getAllTasks()
}
}
fun addTask(title: String) {
viewModelScope.launch {
taskRepository.addTask(Task(title = title))
loadTasks() // 重新加载列表
}
}
}
- UI 共享实践: Compose Multiplatform 实现跨平台 UI。
// Compose Multiplatform 共享 UI 组件
@Composable
fun TaskListScreen(
tasks: List<Task>,
onTaskClick: (Task) -> Unit,
onAddTask: () -> Unit
) {
Column(
modifier = Modifier.fillMaxSize().padding(16.dp)
) {
Text(
text = "任务列表",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(bottom = 16.dp)
)
LazyColumn {
items(tasks) { task ->
TaskItem(
task = task,
onClick = { onTaskClick(task) }
)
}
}
FloatingActionButton(
onClick = onAddTask,
modifier = Modifier.align(Alignment.End)
) {
Icon(Icons.Default.Add, contentDescription = "添加任务")
}
}
}
- 状态与导航管理: 使用 Voyager 或 Decompose 进行跨平台状态与导航管理。
// 使用 expect/actual 处理平台差异的导航示例
// 共享模块中的 expect 声明
expect class PlatformNavigator() {
fun navigateTo(screen: Screen)
fun goBack()
}
// Android 平台的 actual 实现
actual class PlatformNavigator actual constructor() {
private val navController = rememberNavController()
actual fun navigateTo(screen: Screen) {
navController.navigate(screen.route)
}
actual fun goBack() {
navController.popBackStack()
}
}
// iOS 平台的 actual 实现(在 iOS 源集中)
// actual class PlatformNavigator actual constructor() {
// // 使用 UIKit 或 SwiftUI 的导航实现
// }
四、 迈向全栈:KMP 在后端与 Web 前端的应用
- Ktor 构建后端 API: 共享数据模型、验证逻辑与业务规则。
// Ktor 后端 API 路由定义示例
fun Application.configureRouting() {
routing {
route("/api/tasks") {
get {
val tasks = taskService.getAllTasks()
call.respond(HttpStatusCode.OK, tasks)
}
post {
val taskRequest = call.receive<TaskRequest>()
val createdTask = taskService.createTask(taskRequest)
call.respond(HttpStatusCode.Created, createdTask)
}
route("/{id}") {
get {
val id = call.parameters["id"]?.toIntOrNull()
?: throw BadRequestException("Invalid ID")
val task = taskService.getTaskById(id)
call.respond(HttpStatusCode.OK, task)
}
put {
val id = call.parameters["id"]?.toIntOrNull()
?: throw BadRequestException("Invalid ID")
val taskRequest = call.receive<TaskRequest>()
val updatedTask = taskService.updateTask(id, taskRequest)
call.respond(HttpStatusCode.OK, updatedTask)
}
delete {
val id = call.parameters["id"]?.toIntOrNull()
?: throw BadRequestException("Invalid ID")
taskService.deleteTask(id)
call.respond(HttpStatusCode.NoContent)
}
}
}
}
}
- Kotlin/JS 与 React: 共享逻辑在 Web 前端的落地。
// Kotlin/JS 与 React 集成示例
// 共享的业务逻辑
class TaskManager(val apiClient: ApiClient) {
suspend fun fetchTasks(): List<Task> {
return apiClient.get("/api/tasks")
}
suspend fun createTask(title: String): Task {
return apiClient.post("/api/tasks", TaskRequest(title = title))
}
}
// React 组件使用共享逻辑
@JsExport
class TaskListComponent(private val taskManager: TaskManager) {
private var tasks: Array<dynamic> = emptyArray()
@JsExport.Ignore
suspend fun loadTasks() {
tasks = taskManager.fetchTasks().toTypedArray()
}
@JsExport
fun render(): dynamic {
return React.createElement("div", null,
React.createElement("h1", null, "任务列表"),
React.createElement("ul", null,
tasks.map { task ->
React.createElement("li", { key: task.id }, task.title)
}
)
)
}
}
- 数据库与缓存: SQLDelight 实现多平台一致的数据库访问。
// SQLDelight 数据库操作示例
// 共享模块中的数据库定义
class TaskDatabase(driver: SqlDriver) {
private val database = TaskDb(driver)
private val queries = database.taskDbQueries
fun getAllTasks(): List<Task> {
return queries.selectAll().executeAsList().map { it.toTask() }
}
fun insertTask(task: Task) {
queries.insertTask(
id = task.id,
title = task.title,
completed = task.completed,
created_at = task.createdAt
)
}
fun updateTask(task: Task) {
queries.updateTask(
title = task.title,
completed = task.completed,
id = task.id
)
}
fun deleteTask(id: Long) {
queries.deleteTask(id)
}
}
// 平台特定的驱动创建
expect fun createSqlDriver(): SqlDriver
// Android 实现
actual fun createSqlDriver(): SqlDriver {
return AndroidSqliteDriver(TaskDb.Schema, context, "tasks.db")
}
// iOS 实现(在 iOS 源集中)
// actual fun createSqlDriver(): SqlDriver {
// return NativeSqliteDriver(TaskDb.Schema, "tasks.db")
// }
五、 新边疆:KMP 在 AI Agent 开发中的潜力
- AI Agent 架构概述: 感知、规划、执行与学习循环。
// AI Agent 基础架构示例
interface AIAgent {
suspend fun perceive(context: AgentContext): Perception
suspend fun plan(perception: Perception): Plan
suspend fun execute(plan: Plan): ActionResult
suspend fun learn(result: ActionResult): LearningOutcome
}
class SimpleAIAgent : AIAgent {
private val memory = mutableListOf<MemoryEntry>()
private val tools = listOf<Tool>(WebSearchTool(), CalculatorTool(), FileSystemTool())
override suspend fun perceive(context: AgentContext): Perception {
return Perception(
userInput = context.userInput,
currentState = context.state,
availableTools = tools,
memory = memory.takeLast(10) // 最近10条记忆
)
}
override suspend fun plan(perception: Perception): Plan {
// 基于感知结果制定计划
val toolToUse = selectTool(perception)
return Plan(
steps = listOf(
Step("使用工具: ${toolToUse.name}", toolToUse),
Step("分析结果", AnalysisAction()),
Step("生成响应", ResponseAction())
)
)
}
override suspend fun execute(plan: Plan): ActionResult {
// 执行计划中的每个步骤
val results = mutableListOf<StepResult>()
for (step in plan.steps) {
val result = step.action.execute(step.context)
results.add(result)
}
return ActionResult(results)
}
override suspend fun learn(result: ActionResult): LearningOutcome {
// 从执行结果中学习
memory.add(MemoryEntry(result, System.currentTimeMillis()))
return LearningOutcome(improved = result.successful)
}
private fun selectTool(perception: Perception): Tool {
// 简单的工具选择逻辑
return perception.availableTools.firstOrNull { it.canHandle(perception.userInput) }
?: perception.availableTools.first()
}
}
- KMP 作为 Agent 的“大脑”: 共享推理逻辑、工具调用封装与记忆管理。
// 共享的 Agent 推理逻辑
class SharedReasoningEngine {
private val knowledgeBase = KnowledgeBase()
private val reasoningRules = listOf<ReasoningRule>()
suspend fun reasonAbout(context: ReasoningContext): ReasoningResult {
return coroutineScope {
// 并行执行多个推理策略
val strategyResults = listOf(
async { deductiveReasoning(context) },
async { inductiveReasoning(context) },
async { abductiveReasoning(context) }
).awaitAll()
// 综合各策略结果
combineResults(strategyResults)
}
}
suspend fun planNextAction(
currentState: AgentState,
goal: Goal
): ActionPlan {
val possibleActions = generatePossibleActions(currentState, goal)
val scoredActions = possibleActions.map { action ->
val score = evaluateAction(action, currentState, goal)
ScoredAction(action, score)
}
return ActionPlan(
bestAction = scoredActions.maxByOrNull { it.score }?.action,
alternativeActions = scoredActions.sortedByDescending { it.score }
)
}
private suspend fun deductiveReasoning(context: ReasoningContext): DeductiveResult {
// 演绎推理实现
return DeductiveResult(conclusions = emptyList())
}
private suspend fun inductiveReasoning(context: ReasoningContext): InductiveResult {
// 归纳推理实现
return InductiveResult(generalizations = emptyList())
}
private suspend fun abductiveReasoning(context: ReasoningContext): AbductiveResult {
// 溯因推理实现
return AbductiveResult(explanations = emptyList())
}
private fun combineResults(results: List<ReasoningResult>): ReasoningResult {
// 综合推理结果
return ReasoningResult(confidence = results.map { it.confidence }.average())
}
}
- 多平台交互界面: 为同一 AI Agent 提供 App、Web、Cli 等多种交互前端。
// 共享的 Agent 交互接口
interface AgentUI {
suspend fun displayMessage(message: AgentMessage)
suspend fun getInput(prompt: String): String
suspend fun showOptions(options: List<String>): Int
suspend fun updateStatus(status: AgentStatus)
}
// Android/iOS 共享的 Compose UI
@Composable
fun AgentChatScreen(
agent: AIAgent,
conversation: List<ChatMessage>,
onSendMessage: (String) -> Unit
) {
Column(
modifier = Modifier.fillMaxSize()
) {
// 消息列表
LazyColumn(
modifier = Modifier.weight(1f),
reverseLayout = true
) {
items(conversation.reversed()) { message ->
ChatBubble(message = message)
}
}
// 输入框
var inputText by remember { mutableStateOf("") }
Row(
modifier = Modifier.fillMaxWidth().padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
TextField(
value = inputText,
onValueChange = { inputText = it },
modifier = Modifier.weight(1f),
placeholder = { Text("输入消息...") }
)
Button(
onClick = {
onSendMessage(inputText)
inputText = ""
},
enabled = inputText.isNotBlank()
) {
Text("发送")
}
}
}
}
// Web 前端实现(Kotlin/JS)
@JsExport
class WebAgentUI : AgentUI {
override suspend fun displayMessage(message: AgentMessage) {
val messageDiv = document.createElement("div")
messageDiv.className = "agent-message"
messageDiv.textContent = message.content
document.getElementById("chat-container")?.appendChild(messageDiv)
}
override suspend fun getInput(prompt: String): String {
return js("prompt(prompt)") as String
}
override suspend fun showOptions(options: List<String>): Int {
val optionText = options.joinToString("\n") { "${it.index + 1}. $it" }
val choice = js("prompt('请选择:\\n' + optionText)") as String
return choice.toIntOrNull()?.minus(1) ?: 0
}
override suspend fun updateStatus(status: AgentStatus) {
document.getElementById("status")?.textContent = status.toString()
}
}
- 实战构想: 基于 KMP 构建跨平台的个人助理、自动化脚本 Agent 或代码生成工具。
// 跨平台代码生成 Agent 示例
class CodeGenerationAgent : AIAgent {
private val codeGenerator: CodeGenerator
private val codeAnalyzer: CodeAnalyzer
private val testGenerator: TestGenerator
suspend fun generateCodeFromSpec(spec: CodeSpec): GeneratedCode {
// 1. 分析需求
val requirements = analyzeRequirements(spec)
// 2. 生成代码结构
val structure = generateStructure(requirements)
// 3. 填充实现
val implementations = generateImplementations(structure)
// 4. 生成测试
val tests = generateTests(implementations)
// 5. 生成文档
val documentation = generateDocumentation(implementations)
return GeneratedCode(
structure = structure,
implementations = implementations,
tests = tests,
documentation = documentation
)
}
suspend fun refactorCode(
existingCode: String,
refactoringGoal: RefactoringGoal
): RefactoringResult {
// 分析现有代码
val analysis = codeAnalyzer.analyze(existingCode)
// 制定重构计划
val refactoringPlan = planRefactoring(analysis, refactoringGoal)
// 执行重构
val refactoredCode = executeRefactoring(existingCode, refactoringPlan)
// 验证重构结果
val validation = validateRefactoring(refactoredCode, analysis)
return RefactoringResult(
originalCode = existingCode,
refactoredCode = refactoredCode,
changes = refactoringPlan.changes,
validationResult = validation
)
}
// 平台特定的代码生成
expect fun generatePlatformSpecificCode(
platform: TargetPlatform,
logic: SharedLogic
): PlatformCode
// Android 实现
actual fun generatePlatformSpecificCode(
platform: TargetPlatform.Android,
logic: SharedLogic
): PlatformCode {
return generateAndroidCode(logic, platform.minSdk, platform.targetSdk)
}
// iOS 实现
actual fun generatePlatformSpecificCode(
platform: TargetPlatform.IOS,
logic: SharedLogic
): PlatformCode {
return generateSwiftCode(logic, platform.deploymentTarget)
}
// Web 实现
actual fun generatePlatformSpecificCode(
platform: TargetPlatform.Web,
logic: SharedLogic
): PlatformCode {
return generateJavaScriptCode(logic, platform.targetBrowsers)
}
}
六、 技术挑战与最佳实践
- 并发与协程: 跨平台协程使用的一致性与陷阱。
- 依赖管理与二进制大小: 优化编译产物,控制包体积。
- 测试策略: 共享测试与平台特定测试的结合。
- 团队协作与模块化: 如何组织大型 KMP 全栈项目。
以下是 KMP 项目中常见的二进制大小优化策略对比:
| 策略名称 | 适用场景 | 预期效果 |
|---|---|---|
| 使用 cinterop 优化 | 需要调用原生 C/C++/Objective-C 库的场景 | 减少不必要的桥接代码,降低二进制大小 10-30% |
| 资源压缩与优化 | 项目包含大量图片、字体、配置文件等资源文件 | 减少资源文件体积 20-50%,降低整体包大小 |
| 代码混淆与优化 | 发布版本需要保护代码逻辑并减小体积 | 移除未使用代码,优化字节码,减小 15-40% |
| 依赖库精简 | 依赖过多第三方库,包含大量未使用功能 | 通过依赖分析工具移除无用依赖,减小 5-25% |
| 编译器优化选项 | 对性能敏感且需要最小化二进制大小的项目 | 启用 -opt、-Xsize 等编译器标志,减小 5-15% |
| 多平台代码分离 | 不同平台功能差异大,共享代码比例不高 | 按平台分离代码,避免打包无用平台代码,减小 20-60% |
| 使用轻量级替代库 | 当前依赖库过于臃肿,有更轻量的替代方案 | 替换为功能相似但体积更小的库,减小 10-30% |
这些策略可以单独或组合使用,根据项目具体情况选择最合适的优化方案。
七、 未来展望与学习路径
- 技术趋势: KMP 与 Compose 的进一步融合,Wasm 支持。
- 社区与资源: 核心学习资料、开源项目与社区动态。
- 入门建议: 从移动端共享逻辑开始,逐步扩展到全栈与 AI 领域。
八、 结语
KMP 为实现“一次编写,多处运行”的全栈开发提供了坚实路径。从成熟的移动端到探索中的 AI Agent,KMP 生态持续进化,为开发者打开了新的可能性。
更多推荐


所有评论(0)