Kotlin Multiplatform Mobile
mobile
Kotlin
architecture
strict_senior
Share Kotlin code between iOS and Android with Kotlin Multiplatform Mobile (KMM).
By alex_dev
12/8/2025
Prompt
Build a Kotlin Multiplatform Mobile (KMM) application for [APP_NAME] that shares business logic between iOS and Android platforms.
Requirements
1. Shared Module Architecture
Create a shared Kotlin module with:
- Domain Models: Data classes for [ENTITY_1], [ENTITY_2], [ENTITY_3]
- Repository Layer: Business logic for data operations
- Use Cases: Application-specific business rules
- expect/actual Pattern: Platform-specific implementations
2. Platform-Specific Implementations
Implement platform drivers for:
- Database Access: SQLite for Android, CoreData/Realm for iOS
- Network Client: Platform-specific HTTP clients
- Storage: SharedPreferences (Android) and UserDefaults (iOS)
- Platform APIs: Camera, location, notifications, etc.
3. Android Application
Build native Android app with:
- MainActivity: Jetpack Compose or XML layouts
- ViewModel: Android Architecture Components
- Dependency Injection: Koin or Hilt
- Coroutines: For async operations
- Material Design: UI components
4. iOS Application
Build native iOS app with:
- SwiftUI Views: Modern declarative UI
- ViewModels: ObservableObject pattern
- Combine: For reactive programming
- iOS Design: Native iOS UI patterns
5. Shared Business Logic
Implement in common module:
- Data validation
- Business rules
- API communication
- State management
- Error handling
Implementation Pattern
// shared/src/commonMain/kotlin/domain/[Entity].kt
data class [Entity](
val id: String,
val [field1]: String,
val [field2]: Int,
val [field3]: Boolean
)
// shared/src/commonMain/kotlin/data/[Entity]Repository.kt
expect class [Platform]Driver
class [Entity]Repository(private val driver: [Platform]Driver) {
suspend fun get[Entities](): List<[Entity]> {
return driver.query[Entities]()
}
suspend fun create[Entity](entity: [Entity]): Result<[Entity]> {
return try {
driver.insert[Entity](entity)
Result.success(entity)
} catch (e: Exception) {
Result.failure(e)
}
}
}
// shared/src/androidMain/kotlin/data/[Platform]Driver.kt
actual class [Platform]Driver(private val context: Context) {
private val db: SQLiteDatabase = // Initialize database
actual suspend fun query[Entities](): List<[Entity]> {
// Android-specific SQLite implementation
val cursor = db.rawQuery("SELECT * FROM [entities]", null)
return cursor.use { /* map to entities */ }
}
}
// shared/src/iosMain/kotlin/data/[Platform]Driver.kt
import platform.Foundation.*
actual class [Platform]Driver {
actual suspend fun query[Entities](): List<[Entity]> {
// iOS-specific implementation using NSUserDefaults or CoreData
return listOf()
}
}
// androidApp/src/main/kotlin/[package]/MainActivity.kt
class MainActivity : AppCompatActivity() {
private val repository = [Entity]Repository([Platform]Driver(this))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
when (val result = repository.get[Entities]()) {
is Result.Success -> updateUI(result.data)
is Result.Error -> showError(result.exception)
}
}
}
}
// iosApp/ContentView.swift
struct ContentView: View {
@StateObject private var viewModel = [Entity]ViewModel()
var body: some View {
List(viewModel.[entities]) { entity in
[Entity]Row(entity: entity)
}
.onAppear {
viewModel.load[Entities]()
}
}
}
class [Entity]ViewModel: ObservableObject {
@Published var [entities]: [[Entity]] = []
private let repository = [Entity]Repository(databaseDriver: [Platform]Driver())
func load[Entities]() {
// Call shared Kotlin code from Swift
repository.get[Entities]() { entities, error in
if let entities = entities {
self.[entities] = entities
}
}
}
}
Project Structure
[project-name]/
├── shared/
│ ├── src/
│ │ ├── commonMain/kotlin/
│ │ │ ├── domain/
│ │ │ ├── data/
│ │ │ └── usecases/
│ │ ├── androidMain/kotlin/
│ │ └── iosMain/kotlin/
│ └── build.gradle.kts
├── androidApp/
│ └── src/main/kotlin/
└── iosApp/
└── iosApp/
Best Practices
- Use expect/actual for platform-specific code
- Keep business logic in commonMain
- Use sealed classes for state management
- Implement proper error handling with Result types
- Use coroutines for async operations
- Follow platform UI guidelines
- Write shared unit tests in commonTest
Tags
kotlin
kmm
multiplatform
cross-platform
Tested Models
gpt-4
claude-3-opus