0Pricing
Kotlin Academy · 课时

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 Logger

iosMain: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 here

iOS 目标平台的 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.kt

CocoaPods / 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. KMP 项目结构:commonMain、androidMain、iosMain
  2. 用于平台 API 的 expect/actual 机制
  3. 共享存储库层与用例层
  4. 使用 Koin 在 KMP 中进行依赖注入
← 返回 Kotlin Academy