一. KMP 和 Compose Multiplatform
在移动应用开发领域,Kotlin Multiplatform Mobile (KMM) 和 Compose Multiplatform 的结合正在成为一种强大的解决方案,旨在减少为不同平台编写和维护相同业务逻辑代码的时间,同时保留原生编程的灵活性和优势。其主要优势包括代码复用、性能优化、平台特性和灵活性、一致的开发体验以及现代化的 UI 构建。具体来说,KMM 和 Compose Multiplatform 允许开发者在 Android 和 iOS 之间共享大部分代码,包括业务逻辑和 UI 组件,生成的代码直接运行在目标平台的原生环境中,从而享受与原生开发相同的性能和系统级优化。通过 expect 和 actual 关键字,开发者可以为不同平台编写特定实现,充分利用各平台特性,而不会妥协于跨平台限制。使用 Kotlin 和 Compose Multiplatform,开发者能在相同的开发环境中进行多平台开发,提升体验和生产力,而基于声明式编程范式的 Compose Multiplatform 简化了复杂的 UI 构建,使代码更清晰、易于维护。
1. 基础概念
Kotlin Multiplatform (KMP) 是 JetBrains 提供的一项功能,允许使用 Kotlin 编写可以在多个平台上运行的代码,目标是通过共享业务逻辑代码减少不同平台开发的重复工作。KMP 支持的平台包括 JVM(用于服务器端和 Android 开发)、JavaScript(用于前端 Web 开发)以及原生平台(如 iOS、Windows、macOS、Linux 等)。
Kotlin Multiplatform Mobile (KMM) 是专注于移动平台的一种 KMP 实现,让开发者能够使用 Kotlin 编写可以在 Android 和 iOS 上运行的共享代码,主要关注移动设备上的应用开发。简单来说,KMM 是 KMP 的一个子集或特化实现。
Compose Multiplatform 是 JetBrains 开发的一种跨平台用户界面 (UI) 框架,基于 Kotlin 和 Jetpack Compose 的设计理念,旨在通过声明式编程范式简化跨平台 UI 构建。
Kotlin 支持多平台开发,提供了三种主要的编译器后端:Kotlin/JVM、Kotlin/JS 和 Kotlin/Native。Kotlin/JVM 将 Kotlin 代码编译成可以在 Java 虚拟机 (JVM) 上运行的字节码,适用于 Android 开发和服务器开发。Kotlin/JS 将 Kotlin 编译为 JavaScript 代码,可在浏览器或 Node.js 环境中运行,用于 Web 前端开发。Kotlin/Native 将 Kotlin 编译为原生二进制代码,直接运行在不依赖 JVM 或 JavaScript 引擎的环境中,支持 iOS、Windows、macOS、Linux 等平台。KMP 结合了这些后端的优势,使开发者能够在统一代码库中针对不同平台开发。
2. KMP 核心原理
KMM 中的 expect/actual 机制是解决平台相关问题的关键语法技术。当需要在业务逻辑中使用平台特定功能时,expect 声明一个协议,定义期望的接口或数据,然后各平台独立实现这个协议。基本流程如下:在 commonMain 目录下建立 expect 类或 Top-Level 方法作为协议声明,然后在 androidMain 和 iosMain 目录中创建完全一致的实现,否则编译器会报错。
例如,平台抽象接口设计可定义一个跨平台共享的接口规范,如 interface Platform { val name: String },用于获取当前运行平台的名称。通过 expect 声明公共函数 expect fun getPlatform(): Platform,然后在各平台实现。Android 端在 androidMain 中实现 actual fun getPlatform(): Platform = AndroidPlatform(),其中 AndroidPlatform 类重写 name 属性为 "Android ${android.os.Build.VERSION.SDK_INT}"。iOS 端在 iosMain 中实现 actual fun getPlatform(): Platform = IosPlatform(),其中 IosPlatform 类重写 name 属性为 UIDevice.currentDevice.systemName()。这种分层架构将平台无关逻辑置于 commonMain,平台相关实现隔离在 androidMain/iosMain,实现业务逻辑与平台特性的解耦,提升代码复用率。
KMM 项目中 iosMain 能直接访问 iOS Framework 的核心原理依赖跨平台代码分层机制、CInterop 原生接口绑定和编译期代码转换。Kotlin/Native 通过 cinterop 工具生成 Objective-C/Swift 绑定的中间层:扫描 iOS Framework 的头文件,自动生成 Kotlin 可调用的 klib 接口文件。Swift 方法需添加 @objc 修饰符以确保可被 Objective-C 运行时识别。在编译阶段,iosMain 代码被编译为 Mach-O 格式的 Framework 或静态库,自动嵌入 Kotlin/Native 运行时以支持跨平台特性,输出 .framework 文件供 Xcode 工程直接依赖。这一设计使得 KMM 在保持原生性能的同时实现逻辑代码的跨平台复用。
cinterop 工具生成 Objective-C/Swift 绑定的中间层是在编译期动态生成的,不会在新建项目时自动生成,而是在首次执行构建任务时触发生成流程。每次修改 .def 配置文件或原生头文件后,重新构建时会增量更新绑定文件。仅当项目中声明了 cinterop 依赖且配置了原生框架调用时才会生成,例如在 Gradle 配置中声明 iosX64 平台并创建 cinterop。生成路径包括 build/bin/native/cinterop/ 下的 .klib 文件、build/bin/iosX64/debugFramework/ 下的 .framework 二进制文件以及 build/generated/cinterop/ 下的 .h 头文件。cinterop 作为 Kotlin/Native 编译管道的前置步骤,通过 Gradle 插件与构建系统深度集成,检测到配置文件时自动注册生成任务。
二. KMM 环境搭建
1. KDoctor
kdoctor 是一个用于验证 Kotlin Multiplatform Mobile (KMM) 开发环境是否正确配置的命令行工具。它会检查系统上的各种依赖和配置,确保已安装并正确配置所有必要软件,如 Android Studio、Xcode、CocoaPods 等。对于首次设置 KMM 环境,建议使用 kdoctor 确认配置。在 macOS 系统上,可通过 Homebrew 安装 kdoctor:brew install kdoctor。安装后,运行 kdoctor 命令进行检查,它将验证 JDK、Android Studio、Xcode 和 CocoaPods 的安装状态。如果所有组件正确安装,输出会表明系统已准备好进行 KMM 开发。
2. Kotlin Multiplatform Plugin
在 Android Studio 中安装 Kotlin Multiplatform 插件:打开 Android Studio,进入 Settings -> Plugins,搜索并安装 Kotlin Multiplatform 插件,然后重启 Android Studio 以激活插件。
三. 项目构建和解析
1. 新建 KMM 项目
打开 Android Studio,选择 New Project,在项目模板中选择 Kotlin Multiplatform App,然后配置项目名称、保存路径和包名。
2. 项目架构和配置
生成的 KMM 项目包含 Android 和 iOS 两个平台的代码,以及一个共享代码模块。项目结构通常包括 .gradle/ 目录(Gradle 构建缓存)、.idea/ 目录(IDE 配置)、android/ 目录(Android 壳工程)、gradle/ 目录(Gradle 环境管理)、ios/ 目录(iOS 壳工程)和 shared/ 目录(共享代码模块)。shared/ 模块包含 src/ 子目录,如 commonMain/、androidMain/ 和 iosMain/,用于存放跨平台和平台特定代码。其他文件如 .gitignore(Git 忽略配置)、build.gradle.kts(构建配置)、gradle.properties(全局属性)、gradlew 和 gradlew.bat(Gradle Wrapper 脚本)、local.properties(本地环境配置)和 settings.gradle.kts(项目设置)共同管理项目构建。
.gradle/ 是 Gradle 构建过程中生成的缓存和临时文件目录,用于加速构建和管理依赖。.idea/ 存储 IDE 配置和元数据。gradle/ 目录包含 gradle-wrapper.jar 和 gradle-wrapper.properties,实现 Gradle 版本自动化管理。shared/ 模块是共享代码的核心,目前主要包含业务逻辑,但可扩展添加 UI 组件和资源。.gitignore 用于指定无需纳入版本控制的文件,如临时文件和编译产物。build.gradle.kts 定义构建逻辑和依赖关系。gradle.properties 定义全局属性和构建环境参数。gradlew 和 gradlew.bat 是 Gradle Wrapper 的启动脚本,确保统一构建环境。local.properties 存储本地敏感配置如 SDK 路径,禁止提交到版本控制。settings.gradle.kts 定义项目结构和模块管理。
四. 配置文件详解
1. build.gradle
在 KMM 项目中,build.gradle 文件是 Gradle 构建工具的核心配置文件,用于定义构建规则、依赖关系和插件设置。项目根目录的 build.gradle 进行全局配置,定义构建工具和共享规则。共享模块的 build.gradle 配置跨平台代码构建,例如通过 kotlin 块声明多平台目标(如 android() 和 iosArm64()),并通过 dependencies 块按平台细分依赖。Android App 模块的 build.gradle 配置 Android 应用构建,而 iOS 模块通常通过共享模块生成的框架集成,无需单独配置。关键配置包括多平台目标声明、依赖分类(如 commonMain、androidMain、iosMain)和 iOS 框架生成(通过 binaries.framework 设置)。常见问题如依赖解析失败可检查仓库配置,插件版本冲突需统一 Kotlin 插件版本,iOS 构建失败可重新生成框架或清理 Xcode 缓存。
2. gradle.properties
gradle.properties 是 Gradle 构建工具的核心配置文件,用于定义全局属性、控制构建环境和优化性能。它可以配置 JVM 内存分配(如 org.gradle.jvmargs=-Xmx4096m)、启用构建缓存(org.gradle.caching=true)以及定义项目全局变量(如 kotlin_version=1.8.21)。在 KMM 项目中,还可配置 Kotlin/Native 编译参数(如 kotlin.native.binary.memoryModel=strict)和管理 Android 与 iOS 构建行为。此外,可用于设置代理和仓库镜像以解决依赖下载慢的问题,或启用实验性功能(如 kotlin.native.enableExperimentalMemoryManager=true)。文件位于项目根目录,仅影响当前项目,需确保键值对格式正确。
3. local.properties
local.properties 是本地开发环境专属的配置文件,用于存储与开发者机器强相关的路径和敏感信息,如 Android SDK 路径、NDK 路径或调试密钥,避免暴露在版本控制中。典型配置包括 sdk.dir=/path/to/sdk 和 ndk.dir=/path/to/ndk。在 KMM 项目中,可通过代码在 build.gradle 中读取这些配置,例如用于签名配置或动态注入环境变量。最佳实践是禁止提交该文件到版本控制,提供模板文件指导团队成员配置,并统一环境管理以确保团队协作稳定性。与 gradle.properties 的区别在于,local.properties 仅本地生效,而 gradle.properties 全局共享。
4. settings.gradle
settings.gradle 是 Gradle 构建系统的核心配置文件,主要负责定义项目结构、管理子模块和配置构建行为。在 KMM 项目中,通过 include 函数声明包含的模块,如 include ':shared', ':androidApp', ':iosApp'。若模块路径非默认,可通过 project 函数调整。它还用于配置插件管理和仓库,例如在 pluginManagement 块中统一 Kotlin 插件版本,或在 dependencyResolutionManagement 块中声明全局仓库地址。通过协调多平台模块和构建环境隔离,settings.gradle 确保跨平台代码与原生模块的高效整合。
5. gradlew
在 KMM 项目中,.gradlew(Unix/Linux/macOS)和 .gradlew.bat(Windows)是 Gradle Wrapper 的启动脚本,用于统一构建环境,确保开发者无需预先安装特定版本的 Gradle。核心文件包括 gradle/wrapper/gradle-wrapper.properties(定义 Gradle 下载地址和版本)和 gradle-wrapper.jar(负责下载和安装指定版本)。使用方式为运行 ./gradlew build(Unix)或 gradlew.bat build(Windows)执行构建任务。提交这些文件到版本控制可确保环境一致性,简化团队协作。常见问题如权限被拒绝可通过 chmod +x gradlew 解决,更新 Gradle 版本需修改 distributionUrl 并运行 wrapper 任务。