Kotlin Multiplatform vs Flutter: Which One to Choose for Your Apps

Kotlin Multiplatform and Flutter are two of the hottest multi/cross-platform app frameworks and are maturing quite fast. Both help you to reuse code when developing apps for Android and iOS. However, these platforms are very different and serve distinct purposes. Having worked with both, I’d like to share what I consider to be each one’s strengths and weaknesses.

Kotlin Multiplatform Mobile (KMM)

Kotlin is a great choice for developing mobile apps. Its conciseness, simplicity, and expressivity allow you to write correct and readable code effortlessly. Kotlin is the suggested language if you are starting a new native Android Project. Hence, if you have to target Android devices, you will probably end with the Android business logic written in Kotlin. Now, imagine being able to put your Android’s business logic code, almost untouched, inside your iOS project as an iOS Framework. KMM is the best tool to do this right now and is being used by companies like VMware, Philips, and Netflix.

Kotlin Multiplatform Mobile code reuse

In KMM, you have a shared folder that is completely reused between platforms. Most of the business logic will be platform-independent. But, when you need to write code that depends on native/system libraries, you can count with KMM’s expect/actual keywords.

With this mechanism, a common source set defines an expected declaration, and platform source sets must provide the actual declaration that corresponds to the expected declaration. This works for most Kotlin declarations, such as functions, classes, interfaces, enumerations, properties, and annotations.

Curious for how it works? Look at this code:

// Shared (Common)
expect fun randomUUID(): String
// Android
import java.util.*
actual fun randomUUID() = UUID.randomUUID().toString()
// iOS
import platform.Foundation.NSUUID
actual fun randomUUID(): String = NSUUID().UUIDString()

(Available in kotlinlang.org/docs)

Very straightforward, right? This way, the randomUUID() function can be used from reused code (common code), with the correct implementation being provided for each platform during compilation. Then, common code is provided for each platform as an Android module or iOS Framework.

Flutter

Flutter is a cross-platform framework to target iOS and Android with a single codebase. Google calls it a “UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop”. One of the superpowers of Flutter is that you can design almost any interaction or animation and have it running the same way in Android and iOS. No need to make special adjustments or to recreate the designed user interface using native platforms. For those who are looking to innovate in UI space or don’t need to make strong use of native features, Flutter is a strong choice.

Flutter platforms

To write Flutter apps, you need to program in Dart. Dart is a C/Javascript/Java-like programming language, that may be very familiar if you have previous contact with some of these languages. New features like sound null safety makes Dart even closer to Kotlin and Swift. But make no mistake: to have modern language features like sealed classes, inline classes you may need to use code generators (Take a look at Remi Rousselet’s Freezed as an example of generated code in Flutter).

Flutter is very easy to use and has a really fast hot reload. It is nice to see your mobile UI rendered in almost real-time in an emulator/simulator as you code. It’s not the best choice if you depend heavily on native features that don’t have an existing library, because otherwise you may have to spend a lot of time making plumbing code for Flutter’s platform channel. Another weakness is that the native UI components are recreated in Flutter’s engine. This means that if a new OS version is released with new UI components, you will have to wait until Flutter catches up to use the newest resources.

My experience with KMM and Flutter in a real world project

Yes, you’re reading right. I worked with KMM for shared business logic between iOS and Android + Flutter for UI in a real-world app, that is yet to be launched. That way, we unified our low-level network code and business logic between platforms with KMM, leaving Flutter with only the UI layer of the app. I will detail the design decisions and how everything went in a next post.

Which one should I choose? Summary:

Kotlin Multiplatform Mobile may be a good choice if…

  • Already have existing native-specific code to be reused.
  • You care about having the most updated native components and want to have a 100% native look and feel on every new OS version.
  • You want to incrementally share code between platforms on an existing codebase.
  • You don’t need to publish a desktop or web version of your app.
  • You don’t want to depend on Flutter engine’s implementation on each platform.
  • Your project isn’t going to be released very soon, or you don’t care about KMM’s being in alpha status right now.
  • Your app is strongly tied to multithread or background processing needs.

Beware: KMM is currently in alpha and the APIs may change until it hits stable. Kotlin native memory management is being replaced (important for iOS). You will need to study how it handles memory management, concurrency and immutability to correctly implement multiplatform code for now. Check: https://kotlinlang.org/docs/native-concurrency.html#global-variables-and-singletons

Flutter may be a good choice if…

  • You are in a small team and don’t have resources for two native UI codebases.
  • Your app depends mostly on simple API and database calls, a common use case in mobile apps. In this scenario, you can avoid writing Flutter’s Platform Channel code as you won’t need to interact with native code.
  • Your app has a custom UI or you are innovating in UI space.
  • You target Web and Desktop besides Mobile and want to have a working solution for these platforms right now.
  • You are ready to make workarounds about some Flutter bugs that are being worked in.

Beware: there are some bugs in iOS Flutter Engine regarding jank on the first time an animation is realized in the app, but a fix is on the works. Check: https://github.com/flutter/flutter/issues/32170

---

Discuss it on Twitter: