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 — спільна логіка на Kotlin з expect/actual для платформенних API без заміни нативного UI
  • Shared module — Gradle-модуль з кодом мережевих запитів, БД, валідації та бізнес-логіки для всіх платформ
  • Expect/actual — механізм оголошення платформенного API в спільному коді з реалізацією під кожну ціль
  • iOS інтеграція — 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 module.

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
// Репозиторій на 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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