← All articles
$ cat articles/java-kotlin-flutter-kmp.md

Java vs Kotlin vs Flutter vs KMP: choosing a mobile stack

A practical guide to choosing between Java, Kotlin, Flutter, and Kotlin Multiplatform based on your product, existing code, and team.

AndroidKotlinFlutterKotlin Multiplatform

Choosing a mobile stack starts with a product question: what must the app do, on which platforms, and who will maintain it? A list of popular technologies cannot answer that on its own.

Java and Kotlin are programming languages. Flutter is a UI framework built around Dart. Kotlin Multiplatform, often shortened to KMP, enables sharing Kotlin code across platforms. They are related choices, but they do not all replace the same part of an application.

Java: consider the code you already have

For an established Android application, working Java code is an asset to evaluate. A rewrite needs a concrete reason: a maintenance problem, a product change, or a capability the current structure makes difficult to deliver.

Android continues to support Java APIs, and Kotlin can coexist with Java in an application. That allows a team to introduce Kotlin incrementally instead of converting every file before delivering another feature. Android’s Kotlin-first approach

My recommendation for an existing Java app is to inspect its boundaries first. Can a new feature be developed independently? Which areas generate defects? What regression checks protect existing behavior? Those answers make a migration plan more useful than a blanket instruction to rewrite.

Kotlin: a strong starting point for native Android

Google recommends Kotlin when starting an Android app. Kotlin also fits the Jetpack Compose UI ecosystem. Its interoperability with Java makes it relevant to both new development and established codebases. Android language guidance

For an Android-focused product, I would usually evaluate Kotlin first. The proposal should still explain architecture, testing, integrations, and release ownership. Choosing a language does not establish those practices automatically.

For a client, a useful question is: “How will the team add and test the next feature?” It reveals more about maintainability than asking whether one language is universally better.

Flutter: share the interface as well as application code

Flutter provides a shared UI toolkit and a Dart-based application layer. It can connect to platform services through native integration mechanisms, including platform channels. Sharing UI does not remove all Android- or iOS-specific work. Flutter architecture

I would consider Flutter when the product benefits from a consistent experience across Android and iOS and the team can maintain the necessary integrations. Before estimating delivery, check the hardest dependency: a payment SDK, a BLE protocol, a camera workflow, or a background task.

A useful early milestone is a small working version of that integration on both platforms. It gives the team evidence before committing to the rest of the interface. Neither shared code nor a framework choice justifies promising that two platforms will cost exactly the same as one.

KMP: choose which parts should be shared

Kotlin Multiplatform supports sharing code while retaining platform-specific implementation where needed. A project can share business logic and keep native interfaces; Compose Multiplatform is an option for sharing UI too. KMP should not be described as requiring either fully shared or fully separate screens. Kotlin Multiplatform documentation

I would evaluate KMP when an existing Android/iOS team wants to reduce duplicated rules without replacing every part of its apps. Start with a bounded candidate such as validation or calculations, then assess the integration and maintenance experience.

The important planning question is ownership: who changes the shared module, who integrates it into iOS, and who checks behavior on both platforms?

A shared calculation is a useful place to start

My public resistance-calculator project gives this discussion a concrete reference.

For a calculator of this kind, I would evaluate sharing the calculation and validation rules while deciding separately how each platform presents the inputs. The acceptance question is specific: do equivalent inputs produce the same expected result on both platforms?

Compare that with a product whose main challenge is a large, shared visual experience. That changes what the team might want to reuse and makes Flutter worth evaluating. Any estimate of delivery savings still needs evidence from the actual project.

Choose against a concrete scenario

My starting recommendations are:

  • Existing Java Android app: preserve working behavior and evaluate incremental Kotlin adoption.
  • New Android-focused product: evaluate native Kotlin first.
  • New Android and iOS product with substantially shared UI: evaluate Flutter alongside the team’s integration needs.
  • Existing native apps with duplicated business rules: evaluate a small KMP module before a broader migration.

These are starting points, not performance rankings. Team experience, accessibility requirements, device behavior, SDK support, and maintenance constraints can change the decision.

Before commissioning the full build, ask for a proposal that identifies the riskiest integration, what will be shared, what remains platform-specific, and how the result will be tested. That turns a technology debate into a delivery decision.

For examples of mobile product work, explore the portfolio.

More articles

Let's talk