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 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-декларация (функция, клас, свойство), а във всеки 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 срещу 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 в зависимост от декларираните цели.

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 трябва да е съвместимо с Objective-C.

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

swift
// iOS приложение: извикване на shared module от 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 + собствен Skia рендерReact + родни компоненти
Общ кодБизнес логика, мрежа, база данни, валидация100% освен родни добавки100% освен родни модули
ПроизводителностРодна (без междинен слой)Висока (Skia Engine)Средна (JSI Bridge)
iOS поддръжкаKotlin/Native (отлична)ОтличнаДобра
Праг на влизанеСреден (Kotlin + родни платформи)Нисък (един език + един UI)Нисък (JS/TS + React)

Кога да изберем KMP: проектът изисква високопроизводителен 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 целта е в бета. За продукционни проекти с роден 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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също