0Pricing
Kotlin Academy · Lekcja

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 Logger

iosMain: 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 here

Konfiguracja 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.kt

Integracja 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:podPublishReleaseXCFramework

Szybkie 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

  1. Struktura projektu KMP: commonMain, androidMain, iosMain
  2. Mechanizm expect/actual dla API platform
  3. Współdzielenie warstw Repository i Use Case
  4. Wstrzykiwanie zależności w KMP za pomocą Koin
← Powrót do Kotlin Academy