KMM in a simple language learning app: was it worth it?

Anton Tarasov
4 min readJul 25, 2023

--

For the last couple of months, I have been studying Thai in a language school. One of the most complex things about Thai is its writing system: lots of characters that look and sound the same. So, I tried using apps for Thai learners but most of them had flaws in both technical and language aspects. Thus, after some R&D and discussion with the teacher, I set out to build my own.

I wanted to try KMM long ago and this was the right moment, so I started with the Android app, keeping in mind that iOS is coming, too. And now, with both app’s basic functionality implemented, is a good time to check out if going KMM was actually worth it. There are a couple things to consider.

Code sharing

The biggest and most obvious advantage of KMM is the ability to share some common code between platforms, making development cheaper, easier and faster. But how much code can be shared? With modern architectural patterns, KMM-ready libraries and DI frameworks, anything not responsible for the app UI or covered by a multiplatform library can be shared. And that is not a small chunk of code.

My project can roughly be split into 3 big parts (not actual modules but rather kinds of modules):

  • Core — the heart of the app, contains all the logic, algorithms and data layer. All code in this group is shared.
  • App — platform-specific UI, Jetpack Compose for Android and SwiftUI for iOS. No shared code here.
  • Libs — modules with shared bindings and their platform-specific implementations.

So, counting only lines of code in Kotlin, Swift and SQL without libraries and generated code, the result for the project is the following:

Lines of code

And without blank lines and imports (there are a lot of them in Kotlin and 99% of them are added automatically anyway), we get this:

Lines of code — no blank lines, no imports

It should be noted that this calculation does not account for build scripts, resources and any other kind of project files. Still, it is a nice result: shared code takes a bit more than one-third of the app for both platforms. And it leaves some room for improvement, too.

Project setup

The days of struggling with specific Android Studio + Gradle + Plugins + Kotlin + Compose versions are in the past now. KMM works mostly hassle-free in its current state. I spent about 6 hours in total converting my modules into KMM ones, making it compile with no errors and work again for Android and making it available for Xcode build, too.

KMM issues

There are several issues that I encountered on iOS (this is the topic for a whole another article):

  • No support for multiple shared modules, types in them are treated as not compatible. The simplest solution is to make one big fat framework for iOS that contains all the code it needs.
  • Basic Kotlin types get translated into not really convenient Kotlin types representations like KotlinLong or KotlinThrowable, and Int64 or NSArray instead of Int or Array.
  • Nullability and typing issues with generics.
  • No way to use coroutines easily like in Android: no cancellation support, threading limitations and others.

They are not impossible to overcome but solutions take time and require writing additional code.

Libs

Engineers that are used to some frameworks and libraries of choice when working on separate Android and iOS apps might find this frustrating, but most of those are not compatible with KMM. No Retrofit, no Room and others. Even java.time.* or org.joda.time.* can’t be used in shared code.

But! There are a lot of KMM-ready libraries for the most common things already available. One of the best places to find one for your use case is this repository.

Stability

Kotlin Multiplatform is in Beta. It is almost stable, but migration steps may be required in the future. We’ll do our best to minimize any changes you have to make.

During the development and even after the release of the second update for both apps, I haven’t found any hidden bugs or crashes originating from shared code. Keeping in mind all known issues and restrictions of KMM on iOS, it is not too hard to get a stable, working code that wouldn’t behave unexpectedly. So far so good, no problems on this side whatsoever.

Conclusions

So, back to the question: was it worth it? For me and this project, the answer is a definite YES. I got to try relatively new technology and didn’t find too many problems with it, both apps turned out great, and I had fun in the process.

Would it make sense for any other project and any other team? As per usual, it depends. Still, KMM is a valid choice for teams that want their apps to have a native look and feel and native performance and that are prepared to spend some time learning about KMM limitations and libraries.

Happy coding!

Check out the app that can help you memorize Thai characters: Learn Thai Alphabet!

--

--