Kotlin MultiPlatform vs Flutter

Sakhawat Hossain
12 min readMar 9, 2024

--

A Complete Guide to Choose the best Framework for your Product

This article is packed with quite a lot of information, which will help anyone to choose the stable/correct platform between KMP and Flutter. I will try to put Flutter and KMP side by side and you can choose any for development or career.

Flutter

Flutter is a free and open-source software development kit (SDK) for creating user interfaces (UIs) with a single codebase. Flutter was developed by Google and can be used to build applications that run on various platforms, such as web browsers, Fuchsia, Android, iOS, Linux, macOS, and Windows. Flutter was first introduced in 2015 and officially launched in May 2017. Flutter allows developers to create fast, beautiful, and expressive UIs for any screen size and device.

Why Flutter?

  • Beautiful user experiences
  • Fast results
  • Productive development
  • Extensible and open model
  • Access to Platform Specific Features
  • Cost Effective
  • Single Codebase

Beautiful user experiences

Flutter empowers designers to create visually stunning user interfaces with fine control over pixels. It features advanced compositing for seamless blending and animation of graphics, video, text, and controls. With a rich set of iOS (Cupertino) and Material widgets, Flutter supports customization or building unique visual components.

Fast results

Flutter delivers high performance on any device. It uses powerful 2D graphics libraries like Skia (the engine behind Chrome and Android) and Impeller to render smooth, crisp graphics at the native speed of your device.

Flutter code runs on the Dart platform, which supports compilation to 32-bit and 64-bit ARM machine code for iOS and Android, JavaScript and WebAssembly for the web, as well as Intel x64 and ARM for desktop devices.

Productive development

Flutter is a cross-platform framework that lets you build native apps for different devices using a single codebase. One of the features that makes Flutter development fast and productive is stateful hot reload.

Stateful hot reload means that you can change the code of your app while it is running, and see the changes reflected in the app immediately, without losing any data or state. This is useful for experimenting with UI design, fixing bugs, or adding features.

How Hot Reload Works?

Hot reload works by injecting the updated source code into the Dart Virtual Machine (DVM). The DVM updates the app’s classes with the new code, and triggers a rebuild of the widget tree. The app’s state is preserved, so you don’t have to restart the app or navigate back to the same screen.

Stateful hot reload is different from hot restart, which also reloads the code, but resets the app’s state to its initial condition. Hot restart is useful for testing initialization logic or clearing data.

Extensible and open model

You can use Flutter with any tool you like (or none at all), and it also has editor extensions for Visual Studio Code and IntelliJ / Android Studio. Flutter offers thousands of packages to help you develop faster, no matter what platform you target. And you can easily access other native code, with support for both FFI (on Android, on iOS, on macOS, and on Windows) and platform-specific APIs.

Flutter architecture

Unlike traditional Android apps or other cross-platform frameworks, Flutter does not rely on the system UI libraries or interpreted languages, which can reduce performance overhead. Flutter also embeds its own copy of Skia, allowing the developer to benefit from the latest improvements regardless of the OS version. Flutter’s engine is platform-agnostic, and it interacts with the native OS through a platform embedder, which is a native app that hosts Flutter.

Extends:

Separate dev/uat/prod falvour or configuration

One of the challenges of developing a cross-platform app is to manage different environments for development, testing and production. You may want to use different API endpoints, configurations, keys, etc. depending on the environment. Flutter provides a way to do this by using flavors for iOS and Android, and build modes for web. You can define different flavors in your Xcode and Android Studio projects, and use them to run or build your app with different settings. For web, you can use different build modes (debug, profile or release) to switch between environments.

Responsive user interface support iOS/Android

UI can vary depending on the platform, such as iOS, Android, or web. For example, iOS and Android have different design guidelines and conventions for UI elements, such as buttons, menus, icons, and gestures.

Web UI can also differ from mobile UI, as web applications need to adapt to different screen sizes and resolutions. One way to create web UI that can adapt to different devices is to use a framework like Flutter, which is a cross-platform toolkit for building UI.

Responsive user interface support web

Adaptive UI means that the UI can change its structure and behavior based on the device type, orientation, or platform. For example, an adaptive UI might use a tab bar on iOS and a navigation drawer on Android, or switch from a grid view to a list view when the device is rotated. For example, a responsive UI might use flexible layouts, media queries, and breakpoints to adjust the size and position of the widgets according to the available space.

One of the main advantages of Flutter is its ability to create adaptive and responsive UIs for web applications. Adaptive UIs are UIs that adjust to different screen sizes, orientations and platforms, while responsive UIs are UIs that respond to user interactions and changes in the app state. Flutter provides a number of widgets and layout options to help developers create adaptive and responsive UIs, such as MediaQuery, LayoutBuilder, Flexible, Expanded, SizedBox, AspectRatio, FittedBox, FractionallySizedBox and more.

Flutter also supports responsive web design (RWD), which is a web design approach that aims to make web pages render well on different devices and window sizes. RWD uses CSS media queries to apply different styles depending on the device characteristics, such as width, height, orientation and resolution. Flutter allows developers to use media queries in their code to access the MediaQueryData object, which contains information about the current device and window.

Security — Biometric/SSL pinning/Anti jailbreak:

Security is an important aspect of any mobile application, especially when dealing with sensitive data or transactions. In this article, we will explore some of the security features that exist in Flutter, such as biometric authentication, SSL pinning, anti-jailbreak/root detection, and SSL pinning.

Networking in flutter is easy and simple. Flutter has available libray which supports multiplatform. One of the most popular library is Dio. It is a powerful HTTP networking package, supports interceptors, aborting and canceling a request, custom adapters, transformers, etc. Though in pactical we havn’t found any easy way to generate code but for chopper it is default. So for the POC we are going with chopper which is also Flutters favorite.

Kotlin MultiPlatform

Kotlin Multiplatform (KMP) by JetBrains enables code-sharing across platforms, including Android, iOS, web, and desktop, streamlining development with shared Kotlin code for enhanced maintainability and efficiency.

Why KMP?

  • Access to Platform Specific Features.
  • Cost Effective.
  • Single Codebase.
  • Code Reusability.
  • Fast and Native Performance.
  • Single Development Team.

Key Features of KMP

Code Reusability

KMP offers a better way of sharing business logic between multiple platforms while writing in a single codebase. This enables more efficiency and less costing while supporting various platforms.

Platform Coverage

Kotlin Multiplatform isn’t limited to mobile platforms; it extends its support to backend development, web apps. This allows for a broader reach and facilitates the creation of end-to-end Kotlin solutions.

Interoperability

Seamlessly integrate existing platform-specific APIs and libraries. Kotlin’s interoperability ensures a smooth transition for developers and allows them to leverage the strengths of each platform. Also it provides a native experience throughout the system.

Improved Developer Productivity

A shared codebase simplifies maintenance and accelerates development. With Kotlin Multiplatform, developers can focus on delivering features rather than managing separate codebases.

Network

KMP offers ktor and Fuel as one of the two used networking libraries. But in most cases, ktor will be the preferable one based on the popularity in the community. Also ktor has good support.

CI/CD

KMP does provide good support for continuous integration and development, configuring the pipeline and other relevant features are also available. Can easily configure the build tools, workflows, and various commands.

Database

SQLDelight, which is a local database for KMP, till now it gets the basic job done. It generates typesafe kotlin APIs from SQL. But it has some issues white setting it up. And there are several conflicts while using its older version with the new android gradle.

Architecture and Design Principles

Clean Architecture

Adopting clean architecture principles ensures a modular and maintainable codebase. Separation of concerns, clear boundaries, and the use of dependency inversion contribute to a scalable and testable architecture. KMP offers a clean way of breaking down the dependencies to respective layers like, Data Layer, Domain layer and Presentation layer.

Design Patterns

Leverage design patterns like MVVM or MVP to structure UI-related code. Kotlin Multiplatform accommodates various design patterns, allowing developers to choose the one that aligns with project goals. Though there is still room to improve the adoption of MVVM for KMP.

Flavor Based Application

Managing configurations for each flavor involves setting up separate resource files, allowing developers to customize app behavior, appearance, and functionality for different versions, configuring different security rules, maintaining unique IDs etc. But in KMP there isn’t a common way of configuring different flavors. Different flavor like (dev, qa, UAT, release), has to configure for android and iOS separately.For example,

KMP Application Artifacts (KMP vs Flutter)

How KMP Compiles APK, AAB or iOS Versions?

When KMP tries to build any platform specific versions it goes through a few steps, as we know that KMP provides platform specific logics and few shared/common logics. SO whenever there are any builds that are ongoing KMP processes the commonMain and then iosMain/androidMain, later the respective platform converts the resources into builds.

How Flutter Compiles APK, AAB or iOS Versions?

What the Flutter Build Release Command Does

The flutter build command compiles the app and prepares it for distribution in the chosen platform’s app store. The release mode uses Dart’s compiler to increase the app’s performance by reducing the size of the package and ensuring fast startup.

  • Flutter build release apk
  • Flutter build web release
  • Flutter Android release

Flutter uses an abstraction layer over native Android and iOS UI libraries, often involving interpreted languages like JavaScript. This adds overhead, especially in UI-app logic interactions. In contrast, Flutter minimizes abstractions by using its own widget set, compiling Dart code into native code. It bypasses system UI libraries, employing Skia for rendering. Flutter includes its Skia copy in the engine, enabling app upgrades for performance improvements, irrespective of the underlying platform’s updates, as seen in Android, Windows, or macOS.

Artifacts Size Comparison

We have took a sample project for both Flutter and KMP, with platforms Android, iOS and Web. And we have tried to build different builds and the results are shown below,

Note: The Size is in MB

[Note: Here the Flutter Debug APK and AAB size is too large compare to release one, due to the debugging overhead that allows for hot reload and source-level debugging. Please follow this link for better understanding.]

Security Considerations

Anti-Jailbreak/Rooting Measures

Implementing measures against jailbreaking/rooting ensures the application’s integrity. Kotlin Multiplatform allows developers to apply platform-specific anti-tampering techniques to secure the app on both Android and iOS.

Secure Data Storage

Utilizing platform-specific secure storage mechanisms like Keystore on Android and Keychain on iOS safeguards sensitive data. Proper encryption and secure storage practices are crucial for protecting user information.

Design Guidelines

Consistent UI/UX

Following platform-specific design guidelines ensures a consistent and intuitive user experience. Kotlin Multiplatform empowers developers to create applications that seamlessly integrate with the native look and feel of each platform.

Custom Fonts

Integrating custom fonts across platforms involves platform-specific implementations. Developers can use Kotlin Multiplatform to provide a unified API for applying custom fonts, maintaining consistency while leveraging platform-specific capabilities.

Customisation

KMP offers various ways of UI behaviors like good animations/transitions, a wide variety of UI components (Buttons, Lists, Grids etc.). In addition, KMP enables platform specific native transitions, which makes the user journey much smoother.

Third-Party Library Integration

Compatibility

Selecting third-party libraries compatible with Kotlin Multiplatform is crucial for seamless integration. Libraries with shared code components or those specifically designed for Kotlin Multiplatform enhance productivity and code consistency.

Dependency Management

Kotlin Multiplatform Gradle plugins simplify dependency management. By defining dependencies in the common module and platform-specific modules, developers can efficiently manage dependencies for different platforms.

In common/shared way few libraries has third party libraries, but we may need to implement platform specific implementation to get the full support. Below are few examples which has no common/shared libraries till now,

  • Firebase (Analytics, Crashlytics, Remote Config etc)
  • MoEnGage
  • mParticle
  • AppsFlyer
  • InterCom
  • Deeplink

But KMP still offers few core functionalities including, Authentication (Biometric, Face ID), Navigation System, good/native UI Animations, Networking (REST, GraphQL), Logger, DataBase (Shared Pref, Local DB), Security (Data Layer, Certificate Pinning, Reverse Eng., Root Protection, Prograurd Support) etc.

[Note: As KMP is still at a stage where the community is still growing, so there are less number of third party libraries and less support from the community compared to other cross platforms.]

Best Practices

Code Organization

Organizing code in a modular structure promotes maintainability and scalability. By adhering to best practices in code organization, developers can easily navigate the project and make informed decisions.

Testing

Implementing unit, integration, and UI testing best practices ensures the reliability of the shared codebase. Leveraging platform-specific testing frameworks enables thorough testing on each platform.

Industry Example KMP

Below are a few applications, which are using KMP as their main development platform. Still there are many companies trying to adopt KMP as their primary development framework. Examples,

Cons

While Kotlin Multiplatform (KMP) offers numerous benefits, it’s important to be aware of potential challenges or limitations. Here are some cons or challenges associated with using Kotlin Multiplatform.

Limited Platform Coverage

While Kotlin Multiplatform supports Android, iOS, and backend development, certain platforms, such as web browsers, might not be fully supported or have mature solutions. The web platform is till in Experimental stage. The platform coverage is evolving, but it’s essential to assess whether your target platforms are well-supported. This means that few platform support is still in a stage where things might not work as expected.

Platform-Specific Features

Some platform-specific features may not be directly accessible from the shared Kotlin code. If an application heavily relies on platform-specific functionalities that aren’t easily abstracted, we might need to resort to platform-specific code in certain cases.

Learning Curve

Adopting Kotlin Multiplatform may require developers to learn new concepts and workflows. If a team is already proficient in platform-specific languages and frameworks, there may be a learning curve associated with adopting Kotlin Multiplatform.

Tooling Maturity

While the tooling for Kotlin Multiplatform has improved, it might not be as mature or feature-rich as platform-specific tools. IDE support, debugging, and profiling tools may not be as advanced for Kotlin Multiplatform compared to dedicated tools for Android Studio or Xcode.

Gradle Build Complexity

Configuring Gradle builds for Kotlin Multiplatform projects, especially for larger projects with complex dependencies, can be challenging. Managing dependencies across different platforms and ensuring consistent build configurations may require additional effort.

Size of Shared Codebase

As the shared codebase grows, it might become challenging to maintain a clear separation of concerns and manage code organization. This is a common concern with any cross-platform approach that aims for a substantial amount of shared code.

Community and Ecosystem

While the Kotlin Multiplatform community is growing, it might not be as large or active as communities around more established cross-platform frameworks. The availability of third-party libraries and community support might vary compared to more widely adopted frameworks.

Continuous Evolution

Kotlin Multiplatform is continuously evolving, and updates may introduce breaking changes. Keeping up with the latest releases and ensuring compatibility with existing code can require ongoing effort.

Platform-Specific Limitations

Some platform-specific limitations may not have direct equivalents in Kotlin Multiplatform. Developers may need to find workarounds or implement platform-specific code for scenarios where Kotlin Multiplatform falls short.

Debugging Across Platforms

Debugging shared code simultaneously across different platforms can be challenging. Platform-specific debugging tools often provide a more seamless debugging experience.

KMP can provide a good ecosystem, but it has basic problems. Few core libraries are still in beta and the community size is small compared to other KMP competitors. Few notable things are,

  • Hard to configure build setup files.
  • Conflicts between any newer version upgrade.
  • Lack of libraries that offer few core implementations like Firebase Auth, Localisation etc.

It’s important to note that the cons mentioned here are not necessarily showstoppers, and many of them are actively being addressed by the Kotlin Multiplatform community. The decision to use Kotlin Multiplatform should be based on a careful evaluation of project’s requirements, team expertise, and the current state of the Kotlin Multiplatform ecosystem.

References

Thanks for reading this article. It takes a lot of effort to write articles, so your appreciations will give me the inspirations to write more.

Happy Reading!

--

--

Sakhawat Hossain

Senior Software Engineer | Android | iOS | Java | Kotlin | Flutter