Struktura projektu KMP: commonMain, androidMain, iosMain
Poznaj hierarchię zestawów źródeł oraz sposób współdzielenia kodu między platformami docelowymi.
Struktura projektu KMP: commonMain, androidMain, iosMain to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Czym jest KMP?
Kotlin Multiplatform (KMP) umożliwia pisanie współdzielonego kodu Kotlin, który kompiluje się do JVM, Androida, iOS (za pośrednictwem Kotlin/Native) i JS. Kod specyficzny dla platformy znajduje się w oddzielnych zestawach źródeł.
// 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") }Hierarchia zestawów źródeł
Zestawy źródeł tworzą hierarchię. commonMain jest jej korzeniem, a androidMain i iosMain od niego zależą. Kod w commonMain jest widoczny dla wszystkich targetów.
// 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: współdzielona logika
Proszę umieścić logikę biznesową, modele domenowe, repozytoria i przypadki użycia w commonMain. Ten kod kompiluje się dla wszystkich targetów.
// 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: kod specyficzny dla Androida
androidMain może korzystać z klas Android SDK. Typowe zastosowanie to implementacje deklaracji expect/actual specyficzne dla Androida.
// 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 LoggeriosMain: kod specyficzny dla iOS
iosMain ma dostęp do frameworków Apple za pośrednictwem mechanizmu interoperacyjności Kotlin/Native. Proszę używać go do implementacji interfejsów API expect/actual dla 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 hereKonfiguracja Gradle dla targetów iOS
W przypadku iOS zwykle deklaruje się trzy targety: x64 (symulator na procesorze Intel), arm64 (urządzenie) oraz simulatorArm64 (symulator na układzie 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) }
}
}Współdzielone zależności w commonMain
Proszę dodać współdzielone zależności (Ktor, SQLDelight, kotlinx.serialization, Koin) do commonMain. Sterowniki specyficzne dla platformy należy umieścić w zestawach źródeł platformy.
// 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: współdzielone testy
Testy w commonTest są uruchamiane na wszystkich targetach. Proszę używać biblioteki Kotlin test i pisać niezależne od targetu testy jednostkowe współdzielonej logiki biznesowej.
// 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)
}
}Pośrednie zestawy źródeł
Można tworzyć pośrednie zestawy źródeł współdzielone przez podzbiór targetów, na przykład nativeMain dla wszystkich targetów natywnych lub appleMain dla iOS i 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) }
}Układ plików projektu
Typowe drzewo katalogów współdzielonego modułu KMP, które wyraźnie rozdziela poszczególne odpowiedzialności.
// 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.ktIntegracja z CocoaPods / SPM
Wtyczka Gradle KMP generuje XCFramework (lub pod CocoaPods), który należy dodać do projektu Xcode, udostępniając współdzielony kod Kotlin jako natywny framework.
// build.gradle.kts for CocoaPods:
kotlin {
cocoapods {
name = "Shared"
version = "1.0"
ios.deploymentTarget = "14.0"
framework { baseName = "Shared" }
}
}
// Run: ./gradlew :shared:podPublishReleaseXCFrameworkSzybkie sprawdzenie
Gdzie należy umieścić współdzieloną logikę biznesową (modele domenowe, przypadki użycia) w projekcie KMP?
Podsumowanie
commonMain zawiera współdzieloną logikę (domenę, repozytoria, przypadki użycia). androidMain/iosMain zawierają implementacje platformowe. commonTest uruchamia testy na wszystkich targetach. Zależności są rozdzielone: współdzielone interfejsy API znajdują się w commonMain, a sterowniki platformowe w zestawach źródeł platformy.
Często zadawane pytania
Czy lekcja „Struktura projektu KMP: commonMain, androidMain, iosMain” jest bezpłatna?
Tak — pełny tekst „Struktura projektu KMP: commonMain, androidMain, iosMain” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Struktura projektu KMP: commonMain, androidMain, iosMain”?
Poznaj hierarchię zestawów źródeł oraz sposób współdzielenia kodu między platformami docelowymi. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Struktura projektu KMP: commonMain, androidMain, iosMain”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Struktura projektu KMP: commonMain, androidMain, iosMain
- Mechanizm expect/actual dla API platform
- Współdzielenie warstw Repository i Use Case
- Wstrzykiwanie zależności w KMP za pomocą Koin