一、 引言:KMP的崛起与全栈愿景

Kotlin Multiplatform (KMP) 已从移动端跨平台的“潜力股”,成长为覆盖前端、后端乃至AI应用的全栈开发利器。本文将探讨如何利用KMP技术栈,构建从传统Android应用到现代AI Agent的完整技术体系。

二、 KMP技术栈全景图

  • 核心层 (Shared): Kotlin Common, Ktor Client/Server, SQLDelight, Serialization
  • UI层 (Platform-Specific): Compose Multiplatform (Desktop/Web), SwiftUI (iOS), Jetpack Compose (Android)
  • 工具链: Gradle KMP插件, CocoaPods集成, 热重载与调试
  • 生态扩展: 与AI框架(如TensorFlow Lite, ONNX Runtime)的KMP适配

三、 第一步:用KMP重构Android应用

  • 业务逻辑共享: 网络请求、数据模型、本地存储的Common实现
  • 平台特性适配: 使用`expect/actual`处理平台差异(如通知、文件系统)
  • 实战案例: 将现有Android App的数据层与业务层迁移至KMP共享模块

四、 跨越平台:进军iOS与桌面端

  • iOS集成策略: 通过Kotlin/Native生成Framework,在SwiftUI中调用
  • 桌面端开发: 使用Compose for Desktop快速构建跨平台GUI
  • 挑战与解决方案: 内存管理、线程模型、UI状态同步的实践经验

五、 构建KMP全栈后端服务

  • Ktor服务端开发: 用纯Kotlin编写RESTful API与WebSocket服务
  • 数据库操作: 使用SQLDelight实现类型安全的跨平台SQL访问
  • 前后端同构优势: 共享数据模型、验证逻辑与DTO,减少重复代码

六、 AI能力集成:从模型推理到智能体(Agent)

  • 本地AI模型部署: 集成TensorFlow Lite或ONNX Runtime到KMP共享模块
  • LLM API调用封装: 为OpenAI、Claude、DeepSeek等提供统一的KMP SDK

以下是一个在KMP共享模块中定义LLM服务接口并调用OpenAI API的Kotlin代码示例:

// 在 shared/src/commonMain/kotlin/com/example/ai/llm/LLMService.kt 中
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import kotlinx.serialization.Serializable

// 1. 定义通用的请求与响应数据模型
@Serializable
data class ChatCompletionRequest(
    val model: String = "gpt-3.5-turbo",
    val messages: List<ChatMessage>,
    val temperature: Double = 0.7,
    val max_tokens: Int? = null
)

@Serializable
data class ChatMessage(
    val role: String, // "system", "user", "assistant"
    val content: String
)

@Serializable
data class ChatCompletionResponse(
    val id: String,
    val choices: List<Choice>,
    val usage: Usage
)

@Serializable
data class Choice(
    val message: ChatMessage,
    val finish_reason: String
)

@Serializable
data class Usage(
    val prompt_tokens: Int,
    val completion_tokens: Int,
    val total_tokens: Int
)

// 2. 定义期望的LLM服务接口(Common Code)
expect class LLMService {
    suspend fun chatCompletion(request: ChatCompletionRequest): Result<ChatCompletionResponse>
}

// 3. 实际实现(在 shared/src/jvmMain/kotlin 或 iosMain 等平台目录中)
// 以JVM/Android实现为例:
actual class LLMService actual constructor(
    private val apiKey: String,
    private val baseUrl: String = "https://api.openai.com/v1"
) {
    private val client = HttpClient {
        expectSuccess = false
        install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) {
            json(kotlinx.serialization.json.Json { ignoreUnknownKeys = true })
        }
    }

    actual suspend fun chatCompletion(request: ChatCompletionRequest): Result<ChatCompletionResponse> {
        return try {
            val response: HttpResponse = client.post("$baseUrl/chat/completions") {
                header(HttpHeaders.Authorization, "Bearer $apiKey")
                header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
                setBody(request)
            }
            if (response.status.isSuccess()) {
                Result.success(response.body())
            } else {
                Result.failure(Exception("API call failed: ${response.status}"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}

// 4. 在共享业务逻辑中使用
class AIChatViewModel {
    private val llmService = LLMService(apiKey = "your-api-key")

    suspend fun getAIResponse(userInput: String): String {
        val request = ChatCompletionRequest(
            messages = listOf(
                ChatMessage(role = "system", content = "你是一个有帮助的助手。"),
                ChatMessage(role = "user", content = userInput)
            )
        )
        return when (val result = llmService.chatCompletion(request)) {
            is Result.Success -> {
                result.value.choices.firstOrNull()?.message?.content ?: "No response"
            }
            is Result.Failure -> {
                "Error: ${result.exception.message}"
            }
        }
    }
}

此代码结构展示了如何在KMP共享模块中:

  1. 定义与平台无关的数据模型和接口。
  2. 利用expect/actual机制为不同平台(JVM、iOS Native等)提供具体的HTTP客户端实现。
  3. 在共享的ViewModel或业务逻辑中统一调用,实现AI能力的一次编写,多端复用。

为了更直观地展示上述代码示例中的数据流与调用关系,下面是一个Mermaid流程图:

flowchart TD
    subgraph "KMP共享模块 (Common Code)"
        A[定义通用数据模型
ChatCompletionRequest等] --> B[定义expect接口
LLMService]
        B --> C[业务逻辑层
AIChatViewModel]
    end

    subgraph "平台特定实现 (Platform-Specific)"
        D[JVM/Android实现
shared/src/jvmMain] --> E[HTTP客户端配置
Ktor Client + JSON序列化]
        F[iOS Native实现
shared/src/iosMain] --> G[NSURLSession封装
或平台HTTP客户端]
        H[其他平台实现
如Desktop/Web]
    end

    subgraph "外部AI服务"
        I[OpenAI API]
        J[Claude API]
        K[DeepSeek API]
    end

    B -->|expect声明| D
    B -->|expect声明| F
    B -->|expect声明| H
    
    E -->|HTTP请求| I
    G -->|HTTP请求| J
    H -->|HTTP请求| K
    
    C -->|调用| B
    D -->|actual实现| E
    F -->|actual实现| G
    
    C -->|返回结果| L[UI层
Compose/SwiftUI]
    
    style A fill:#e1f5fe
    style B fill:#e1f5fe
    style C fill:#e1f5fe
    style D fill:#f3e5f5
    style F fill:#f3e5f5
    style H fill:#f3e5f5
    style I fill:#f1f8e9
    style J fill:#f1f8e9
    style K fill:#f1f8e9
    style L fill:#fff3e0

该流程图清晰地展示了KMP架构下AI服务集成的完整流程:

  1. 通用层定义:在共享模块中定义与平台无关的数据模型和接口。
  2. 平台特定实现:通过expect/actual机制为不同平台提供具体的HTTP客户端实现。
  3. 外部服务集成:各平台实现调用对应的AI服务API(OpenAI、Claude、DeepSeek等)。
  4. 统一业务调用:共享的ViewModel或业务逻辑通过统一的接口调用AI服务,结果返回给各平台UI层。
  • 构建AI Agent框架: 设计可组合的“工具(Tools)”、“记忆(Memory)”、“规划(Planning)”共享组件
  • 案例:智能客服助手: 跨平台界面 + 共享业务逻辑 + 统一的AI对话引擎

七、 工程化与部署实践

  • 模块化架构设计: 清晰划分`shared`, `androidApp`, `iosApp`, `desktopApp`, `backend`模块
  • CI/CD流水线: 使用GitHub Actions/Jenkins实现多平台自动构建与测试
  • 性能监控与优化: 针对各平台特性的性能分析工具与调优策略

八、 未来展望:KMP在AI Native时代的机会

  • KMP作为“AI原生应用”的统一逻辑层潜力
  • 与新兴AI框架(如LangChain的Kotlin版本)的生态结合
  • 对边缘计算与物联网(IoT)场景的适配

九、 总结与资源推荐

  • 核心价值总结: 一次编写,多处运行;统一技术栈,降低全栈复杂度。
  • 学习路径: 官方文档 → 基础共享模块实践 → 多平台UI集成 → 后端与AI扩展。
  • 推荐资源: Kotlin官方KMP示例、开源KMP全栈项目(如KMM-Playground)、相关技术社区。

下一步行动清单

为了帮助你将KMP全栈开发理念付诸实践,以下是你可以立即尝试的5个具体步骤:

  1. 在现有Android项目中创建KMP共享模块:使用Android Studio的KMP模板或手动配置build.gradle.kts,创建一个shared模块,将网络请求、数据模型等业务逻辑迁移至此。
  2. 将某个核心数据模型迁移至共享模块:选择一个简单的数据类(如UserProduct),用@Serializable注解标记,并确保其在Android和iOS端都能正常序列化/反序列化。
  3. 为iOS平台编写actual实现:在shared/src/iosMain/kotlin目录下,为一个expect声明的平台相关功能(如文件存储、本地通知)提供基于iOS原生API的actual实现。
  4. 封装一个简单的Ktor Client API调用:在共享模块中定义一个expect的HTTP客户端接口,并分别在jvmMainiosMain中提供实际实现,调用一个公开的REST API(如天气接口)。
  5. 尝试集成一个AI能力:参考本文第六节的代码示例,在共享模块中定义一个LLM服务接口,并先为Android/JVM平台实现一个调用OpenAI或DeepSeek API的实际版本,体验一次编写、多端复用的优势。

完成以上步骤后,你将初步掌握KMP的核心开发流程,并能够在此基础上逐步构建更复杂的全栈应用。

Logo

一站式 AI 云服务平台

更多推荐