Kotlin Multiplatform: что это, shared module и expect/actual

Автор: IT Sectr Опубликовано: 2026-02-11 Время чтения: 11 мин

Kotlin Multiplatform (KMP) — технология JetBrains, компилирующая общий Kotlin-код сразу под iOS, Android, Web и Desktop. В отличие от Flutter и React Native, KMP не заменяет нативные UI — общая логика выносится в shared module, а интерфейс каждого приложения остаётся нативным. Kotlin Multiplatform documentation — главный справочник по настройке модулей и expect/actual механизму.

Главное

  • KMP — shared логика на Kotlin с expect/actual для платформенных API без замены нативного UI
  • Shared module — Gradle-модуль с кодом сетевых запросов, БД, валидации и бизнес-логики для всех платформ
  • Expect/actual — механизм объявления платформенного API в общем коде с реализацией под каждую цель
  • iOS integration — shared module компилируется в Apple framework через Kotlin/Native
  • KMP vs KMM — Kotlin Multiplatform Mobile (мобильный фокус) теперь часть общего Kotlin Multiplatform

Что такое Kotlin Multiplatform?

Kotlin Multiplatform — технология кросс-компиляции, позволяющая писать общий код на Kotlin и компилировать его под разные платформы: JVM (Android), LLVM (iOS, macOS, watchOS), JavaScript (Web) и нативные бинарники (Linux, Windows). KMP не является фреймворком UI — он решает задачу переиспользования бизнес-логики, а не интерфейсов.

Архитектура KMP строится вокруг shared module — Gradle-модуля, содержащего commonMain с независимым от платформы кодом и source sets для каждой цели (androidMain, iosMain, desktopMain). По данным JetBrains за 2025, более 40% новых Kotlin-проектов используют KMP для обмена кодом между платформами.

Kotlin Multiplatform Mobile (KMM) — предыдущее название для мобильного сценария iOS+Android. С Kotlin 2.1+ термин KMM заменён на общий Kotlin Multiplatform, так как технология вышла за пределы мобильной разработки. Netflix, McDonald's и VMware используют KMP в продакшене для шаринга кода между мобильными приложениями.

Механизм expect/actual: архитектура

Expect/actual — ключевой механизм KMP для работы с платформенным кодом. В commonMain объявляется expect-декларация (функция, класс, property), а в каждом platform-specific source set (androidMain, iosMain) — actual-реализация. Компилятор проверяет, что для каждого expect существует actual в каждой целевой платформе.

kotlin
// commonMain — объявление платформенного API
expect fun getPlatformName(): String

expect class PlatformContext(val appVersion: String)

// androidMain — actual под Android
actual fun getPlatformName(): String = "Android \${Build.VERSION.SDK_INT}"

// iosMain — actual под iOS
actual fun getPlatformName(): String =
    UIDevice.currentDevice.systemName

Иерархия source sets в KMP позволяет создавать промежуточные уровни: например, iosArm64Main (физические устройства iOS) и iosSimulatorArm64Main (симулятор) с общим iosMain. Код из commonMain доступен всем платформам, а код из iosMain — только iOS-целям. Это сокращает дублирование, когда реализация отличается не для каждой платформы, а для группы платформ.

На практике expect/actual используется для: получения локального хранилища (SharedPreferences vs NSUserDefaults), работы с сетью (HttpEngine под каждую платформу), доступа к файловой системе, криптографии и аналитики. JetBrains рекомендует минимизировать количество expect/actual и выносить как можно больше кода в commonMain.

Shared module: структура и Gradle

Shared module — стандартный Gradle-модуль с плагином `org.jetbrains.kotlin.multiplatform`. Он содержит общий код в `src/commonMain/kotlin/` и платформенные реализации в `src/androidMain/kotlin/` и `src/iosMain/kotlin/`. KMP-проект также подключает `androidApp` и `iosApp`, которые зависят от shared модуля.

kotlin
// build.gradle.kts — shared module
plugins {
    kotlin("multiplatform")
    id("com.android.library")
}

kotlin {
    androidTarget()
    
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach {
        it.binaries.framework {
            baseName = "shared"
            isStatic = true
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:3.1.0")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:3.1.0")
            }
        }
        val iosMain by creating {
            dependencies {
                implementation("io.ktor:ktor-client-darwin:3.1.0")
            }
        }
    }
}

Конфигурация Gradle для KMP требует явного указания iOS-целей — x64 (симулятор Intel), arm64 (физические устройства) и simulatorArm64 (симулятор Apple Silicon). Для каждой цели генерируется отдельный Apple framework. Плагин `kotlin("multiplatform")` автоматически настраивает компиляцию под JVM и LLVM в зависимости от объявленных target.

Ktor и kotlinx.serialization — стандартные библиотеки KMP, поддерживающие общий код. Ktor предоставляет HTTP-клиент с движками под каждую платформу (OkHttp для Android, Darwin для iOS). kotlinx.serialization работает на любых платформах без expect/actual благодаря мультиплатформенной реализации в commonMain.

Интеграция с iOS через Kotlin/Native

Kotlin/Native — компилятор Kotlin в нативный код через LLVM. Для iOS shared module компилируется в Apple framework (.framework), который подключается через Xcode. Вызов общего кода из Swift/Objective-C происходит через сгенерированные Objective-C заголовки, поэтому API shared module должен быть compatible с Objective-C.

Ограничения iOS интеграции: Kotlin коллекции (List, Map) конвертируются в NSArray/NSDictionary. Функции с параметрами по умолчанию не экспортируются — нужны overloads. Для suspend-функций генерируются callback-based методы с `@ObjCName` и async/await поддержка с Kotlin 2.0+.

swift
// iOS-приложение: вызов shared модуля из Swift
import shared

class ViewModel: ObservableObject {
    let repository = UserRepository()
    
    func loadUsers() {
        repository.fetchUsers(completionHandler: { result, error in
            if let users = result as? [User] {
                print("Users: \(users.count)")
            }
        })
    }
}

Интеграция shared module в Xcode происходит через embed-and-framework — сгенерированный `.xcframework` добавляется в Xcode проект. Gradle плагин может автоматически обновлять framework при сборке через embedAndSignAppleFrameworkForXcode. Для тестирования на симуляторе достаточно iosSimulatorArm64 или iosX64 бинарника.

KMP vs Flutter vs React Native

Выбор между KMP, Flutter и React Native зависит от приоритета: переиспользование логики или полная кроссплатформа. KMP даёт нативный UI на каждой платформе, но требует двух кодовых баз для интерфейса. Flutter и React Native используют единый UI, но жертвуют нативностью.

ХарактеристикаKMPFlutterReact Native
UI-фреймворкНативный (Android XML/Jetpack Compose + SwiftUI)Dart + собственный рендер SkiaReact + нативные компоненты
Общий кодБизнес-логика, сеть, БД, валидация100% кроме нативных плагинов100% кроме нативных модулей
ПроизводительностьНативная (нет прослойки)Высокая (Skia Engine)Средняя (JSI Bridge)
iOS поддержкаKotlin/Native (отличная)ОтличнаяХорошая
Входной порогСредний (Kotlin + нативные платформы)Низкий (один язык + один UI)Низкий (JS/TS + React)

Когда выбрать KMP: проект требует high-performance UI (игры, карты, анимации), существующий нативный код надо переиспользовать, команда уже знает Kotlin и нативные платформы. Когда выбрать Flutter/RN: MVP или стартап с ограниченным бюджетом, команда одного профиля, UI не требует глубокой нативной кастомизации.

Инструменты и библиотеки KMP

Экосистема KMP инструментов включает библиотеки для всех слоёв приложения: сеть (Ktor), сериализация (kotlinx.serialization), БД (SQLDelight), навигация (Decompose), DI (Koin) и хранение данных (multiplatform-settings). JetBrains поддерживает Compose Multiplatform — UI-фреймворк на Kotlin, работающий на всех платформах.

kotlin
// Repository на KMP с SQLDelight + Ktor
class UserRepository(
    private val httpClient: HttpClient,
    private val db: AppDatabase
) {
    suspend fun syncUsers(): List<User> {
        val remote = httpClient.get("https://api.example.com/users")
            .body<List<UserDto>>()
        
        db.userQueries.replaceAll(remote.map { it.toDomain() })
        
        return db.userQueries.selectAll().executeAsList()
    }
}

Compose Multiplatform — UI-фреймворк для KMP, основанный на Jetpack Compose. Позволяет писать интерфейс на Kotlin для Android, iOS, Desktop и Web. В 2025 году Compose Multiplatform достиг стабильного статуса для Android и Desktop; iOS-таргет в beta. Для production-проектов с нативным UI преимущество KMP остаётся главным отличием от Flutter.

Часто задаваемые вопросы

Чем Kotlin Multiplatform отличается от Kotlin Multiplatform Mobile?

KMM — это мобильный сценарий KMP для iOS и Android. С версии Kotlin 2.1+ JetBrains объединила оба термина в Kotlin Multiplatform, так как технология поддерживает не только мобильные платформы, но также Desktop и Web. KMM-проекты продолжают работать, но теперь это часть общего KMP.

Можно ли использовать KMP с SwiftUI?

Да. KMP компилируется в Apple framework через Kotlin/Native с Objective-C заголовками. SwiftUI импортирует этот framework как обычную библиотеку. Shared module экспортирует Kotlin-классы и функции, которые вызываются из Swift с некоторыми ограничениями (например, Kotlin коллекции конвертируются в Foundation типы).

Как тестировать shared module на iOS?

На iOS shared module тестируется через Kotlin/Native тесты в iosTest source set. Для UI-тестов используется XCTest в Xcode с импортированным framework. Kotlin-тесты пишутся на commonTest с kotlin.test и выполняются на iOS-симуляторе через Gradle таск iosSimulatorArm64Test.

Какие библиотеки доступны в KMP?

Основные KMP библиотеки: Ktor (сеть), kotlinx.serialization (JSON), SQLDelight (БД), Koin (DI), Decompose (навигация), multiplatform-settings (SharedPreferences/NSUserDefaults), Apollo GraphQL, Firebase (через KMP-NativeCoroutines). Compose Multiplatform предоставляет UI для всех платформ.

Поддерживает ли KMP Gradle 8?

Да. KMP полностью совместим с Gradle 8.5+. Начиная с Kotlin 2.1, официальные плагины поддерживают Gradle 8. Конфигурация через build.gradle.kts с kotlin("multiplatform") требует Gradle 7.6+, но рекомендуется версия 8.5 для оптимальной производительности сборки.

Итоги

  • Kotlin Multiplatform — кросс-платформенная технология JetBrains для общего кода без замены нативного UI
  • Expect/actual — механизм объявления платформенных API в commonMain с реализациями под каждую цель
  • Shared module — Gradle-модуль с commonMain и платформенными source sets (androidMain, iosMain)
  • Kotlin/Native компилирует shared module в Apple framework, вызываемый из Swift и Objective-C
  • KMP vs Flutter/RN — переиспользование логики + нативный UI против единой кодовой базы и UI
  • Compose Multiplatform — UI-фреймворк на Kotlin для Android, iOS, Desktop и Web
  • Экосистема — Ktor, SQLDelight, Koin, kotlinx.serialization, Decompose для всех слоёв приложения

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также