0Pricing
Kotlin Academy · Урок

Структура проекта KMP: commonMain, androidMain, iosMain

Разберитесь в иерархии наборов исходного кода и в совместном использовании кода между целевыми платформами.

«Структура проекта KMP: commonMain, androidMain, iosMain» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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.

// 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 получает доступ к фреймворкам Apple через взаимодействие Kotlin/Native. Используйте его для реализаций API 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

Конфигурация Gradle для целей iOS

Для 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 для всех нативных платформ или appleMain для iOS и macOS.

// 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), который добавляется в проект 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» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Структура проекта KMP: commonMain, androidMain, iosMain»?

Разберитесь в иерархии наборов исходного кода и в совместном использовании кода между целевыми платформами. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Структура проекта KMP: commonMain, androidMain, iosMain»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Структура проекта KMP: commonMain, androidMain, iosMain
  2. Механизм expect/actual для API платформ
  3. Общие слои репозитория и вариантов использования
  4. Внедрение зависимостей в KMP с Koin
← Назад к Kotlin Academy