KMP 项目结构:commonMain、androidMain、iosMain
理解源集层次结构,以及代码如何在不同目标之间共享。
KMP 项目结构:commonMain、androidMain、iosMain 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
什么是 KMP
Kotlin Multiplatform(KMP)允许您编写共享的 Kotlin 代码,并将其编译为 JVM、Android、iOS(通过 Kotlin/Native)和 JS。平台特定的代码位于单独的源集中。
// Typical KMP module structure:
// shared/
// src/
// commonMain/kotlin/ <- shared code
// androidMain/kotlin/ <- Android-only
// iosMain/kotlin/ <- iOS-only
// commonTest/kotlin/ <- shared tests
fun main() { println("KMP: one codebase, many targets") }源集层次结构
源集构成一个层次结构。commonMain 是根源集;androidMain 和 iosMain 依赖于它。commonMain 中的代码对所有目标平台可见。
// build.gradle.kts (Kotlin DSL)
kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val commonMain by getting {
dependencies { /* shared deps */ }
}
val androidMain by getting
val iosMain by getting
}
}commonMain:共享逻辑
请将业务逻辑、领域模型、仓库和用例放入 commonMain。这些代码会为所有目标平台编译。
// commonMain/kotlin/com/example/domain/User.kt
data class User(val id: String, val name: String, val email: String)
// commonMain/kotlin/com/example/repository/UserRepository.kt
interface UserRepository {
suspend fun getUser(id: String): User?
suspend fun saveUser(user: User)
}androidMain:Android 特定代码
androidMain 可以使用 Android SDK 类。典型用途包括:为 expect/actual 声明提供 Android 特定的实现。
// androidMain/kotlin/com/example/platform/PlatformLogger.kt
import android.util.Log
class AndroidLogger : Logger {
override fun log(msg: String) = Log.d("App", msg)
}
// androidMain/kotlin/com/example/di/PlatformModule.kt
// Koin or Hilt module that binds AndroidLogger to LoggeriosMain:iOS 特定代码
iosMain 通过 Kotlin/Native 互操作访问 Apple 框架。请使用它为 expect/actual 接口提供 iOS 实现。
// iosMain/kotlin/com/example/platform/PlatformLogger.kt
import platform.Foundation.NSLog
class IosLogger : Logger {
override fun log(msg: String) = NSLog(msg)
}
// iOS uses Kotlin/Native runtime; no JVM hereiOS 目标平台的 Gradle 配置
对于 iOS,通常需要声明三个目标平台:x64(Intel 处理器上的模拟器)、arm64(设备)和 simulatorArm64(Apple Silicon 上的模拟器)。
// build.gradle.kts
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val iosMain by creating {
dependsOn(commonMain.get())
}
val iosX64Main by getting { dependsOn(iosMain) }
val iosArm64Main by getting { dependsOn(iosMain) }
val iosSimulatorArm64Main by getting { dependsOn(iosMain) }
}
}commonMain 中的共享依赖
请将共享依赖项(Ktor、SQLDelight、kotlinx.serialization、Koin)添加到 commonMain。平台特定的驱动程序应放在平台源集中。
// commonMain dependencies example:
// implementation("io.ktor:ktor-client-core:2.3.0")
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// implementation("io.insert-koin:koin-core:3.4.0")
// androidMain:
// implementation("io.ktor:ktor-client-okhttp:2.3.0")
// iosMain:
// implementation("io.ktor:ktor-client-darwin:2.3.0")commonTest:共享测试
commonTest 中的测试会在所有目标平台上运行。请使用 Kotlin 测试库,并为共享业务逻辑编写与目标平台无关的单元测试。
// commonTest/kotlin/UserRepositoryTest.kt
import kotlin.test.Test
import kotlin.test.assertEquals
class UserRepositoryTest {
@Test
fun testUserCreation() {
val user = User("1", "Alice", "alice@example.com")
assertEquals("Alice", user.name)
}
}中间源集
您可以创建在部分目标平台之间共享的中间源集,例如,用于所有原生目标平台的 nativeMain,或用于 iOS 和 macOS 的 appleMain。
// Create appleMain shared between iOS and macOS:
sourceSets {
val appleMain by creating { dependsOn(commonMain.get()) }
val iosMain by getting { dependsOn(appleMain) }
val macosMain by getting { dependsOn(appleMain) }
}项目文件布局
典型的 KMP 共享模块目录树,可以清晰地分离各项职责。
// shared/
// build.gradle.kts
// src/
// commonMain/kotlin/
// domain/ User.kt, Post.kt
// repository/ UserRepository.kt
// usecase/ GetUserUseCase.kt
// androidMain/kotlin/
// repository/ RoomUserRepository.kt
// iosMain/kotlin/
// repository/ CoreDataUserRepository.kt
// commonTest/kotlin/ GetUserUseCaseTest.ktCocoaPods / SPM 集成
KMP Gradle 插件会生成 XCFramework(或 CocoaPods pod)。您可以将其添加到 Xcode 项目中,从而将共享 Kotlin 代码作为原生框架公开。
// build.gradle.kts for CocoaPods:
kotlin {
cocoapods {
name = "Shared"
version = "1.0"
ios.deploymentTarget = "14.0"
framework { baseName = "Shared" }
}
}
// Run: ./gradlew :shared:podPublishReleaseXCFramework快速检查
在 KMP 项目中,共享业务逻辑(领域模型、用例)应放在哪里?
总结
commonMain 存放共享逻辑(领域、仓库、用例)。androidMain/iosMain 存放平台实现。commonTest 会在所有目标平台上运行测试。依赖项需要分开管理:共享 API 放在 commonMain 中,平台驱动程序放在平台源集中。
常见问题解答
「KMP 项目结构:commonMain、androidMain、iosMain」课时是免费的吗?
是的 — 「KMP 项目结构:commonMain、androidMain、iosMain」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「KMP 项目结构:commonMain、androidMain、iosMain」这节课中我会学到什么?
理解源集层次结构,以及代码如何在不同目标之间共享。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「KMP 项目结构:commonMain、androidMain、iosMain」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- KMP 项目结构:commonMain、androidMain、iosMain
- 用于平台 API 的 expect/actual 机制
- 共享存储库层与用例层
- 使用 Koin 在 KMP 中进行依赖注入