Kotlin Multiplatform vs Flutter
JetBrains Kotlin Multiplatform versus Google Flutter: native UI versus shared UI, performance, ecosystem, and 2026 enterprise mobile choice.
Share only the business logic, keep the UI native
Produce UI + business logic together from a single codebase
There's no clear-cut winner — it depends on your scenario. If you want the UI to stay fully native and only share the network/data/business-logic layer, and your team already leans Kotlin/Android, choose KMP: the official tutorial spells out adding the shared module to Android via Gradle and linking it into iOS as an Xcode framework. If you want to produce screens from a single codebase and bring your web team into mobile, React Native stands out: a 126,703-star ecosystem and the official "Integration with Existing Apps" guide back that up.
| Category | Kotlin Multiplatform | React Native |
|---|---|---|
| Performance | 8/10 | 7/10 |
| Ease of Learning | 6/10 | 7/10 |
| Ecosystem | 6/10 | 9/10 |
| Community | 6/10 | 9/10 |
| Job Market | 6/10 | 7/10 |
| Future-Proof | 8/10 | 8/10 |
// KMP shared module — adding to an existing Android/iOS app
// shared/src/commonMain/kotlin/data/UserRepository.kt
package com.app.shared.data
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.Serializable
@Serializable
data class User(val id: String, val name: String, val avatarUrl: String)
// Note: kotlin.Result is a value class and doesn't export to Objective-C;
// the return type is User directly, the error path goes via throws/completion error.
class UserRepository(private val api: UserApi) {
suspend fun fetchUser(id: String): User = api.getUser(id)
}
// expect/actual: the platform-specific part (iOS Keychain / Android EncryptedSharedPreferences)
expect class SecureStorage {
fun save(key: String, value: String)
fun read(key: String): String?
}
// shared/build.gradle.kts (summary)
kotlin {
androidTarget()
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach {
it.binaries.framework { baseName = "Shared" }
}
sourceSets {
commonMain.dependencies {
implementation("io.ktor:ktor-client-core:3.6.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
}
}
}
// Linking it in on the iOS side as an Xcode framework (Swift)
import Shared
let repo = UserRepository(api: UserApiImpl())
repo.fetchUser(id: "42") { user, error in
if let user = user { print(user.name) }
}// React Native — integrating into an existing app; index.js: register the screen
import { AppRegistry } from 'react-native';
import ProfileScreen from './src/ProfileScreen';
AppRegistry.registerComponent('ProfileScreen', () => ProfileScreen);
// src/ProfileScreen.tsx — Strict TypeScript API (default as of RN 0.87)
import { View, Text } from 'react-native';
export default function ProfileScreen({ userId }: { userId: string }) {
return (
<View style={{ padding: 16 }}>
<Text style={{ fontSize: 17 }}>User {userId}</Text>
</View>
);
}
// android/app/build.gradle — RN Gradle Plugin (summary)
apply plugin: "com.facebook.react"
react { autolinkLibrariesWithApp() }
// MyReactActivity.kt — the pattern from the official guide
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
class MyReactActivity : ReactActivity() {
override fun getMainComponentName(): String = "ProfileScreen"
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
// AndroidManifest.xml: <activity android:name=".MyReactActivity"
// android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
// from your existing Activity: startActivity(Intent(this, MyReactActivity::class.java))There's no clear-cut winner — it depends on your scenario. If you want the UI to stay fully native and only share the network/data/business-logic layer, and your team already leans Kotlin/Android, choose KMP: the official tutorial spells out adding the shared module to Android via Gradle and linking it into iOS as an Xcode framework. If you want to produce screens from a single codebase and bring your web team into mobile, React Native stands out: a 126,703-star ecosystem and the official "Integration with Existing Apps" guide back that up.
Get Free ConsultationThere's no single right answer — it depends on team skills: if you're a Kotlin/Android team and want the UI to stay native, pick KMP; if you're a web/React team and want to produce screens from a single codebase, pick React Native. Both officially support incremental addition to an existing app.