Introduction to Kotlin Multiplatform

We’ve just finished building our first commercial project using Kotlin Multiplatform. In the first of an ongoing series Douglas Hoskins, our Head of Mobile, gives an overview and some initial thoughts. We’re already working on future posts that will go into more detail and explain how we used this emerging technology.

Mobile development in 2019. The choice for developers is greater than ever in terms of frameworks and architecture.

But there’s one approach in particular that is getting the team at Future Platforms very excited indeed: it’s Kotlin Multiplatform.

Kotlin has been the language of choice for the modern, discerning Android developer for some time now. Its impact on the scene has been similar to that of Swift in the iOS community.

It’s been a breath of fresh air for those used to Java. Verbose, boilerplate-heavy code has made way for powerful, expressive Kotlin. It makes codebases more readable, and its null-safety eliminates entire classes of bugs. Android developers have embraced it in droves.

As the name suggests, Kotlin Multiplatform is a framework which allows Kotlin code to run on many target platforms.

This includes iOS!

It’s been around in beta form for quite a while, and it’s now ready for production. In fact, we’ve just finished a large project using it.

This post will introduce the platform and explain why we think it’s a great approach for cross platform app development.

Let’s set the scene. You should seriously consider Kotlin Multiplatform if:

  • You are building apps for both iOS and Android
  • Which are equivalent in terms of functionality and user journey
  • But the UI should still reflect the finer nuances of the target platform

This brings us to the first key thing to understand about Kotlin Multiplatform: there is no shared UI. The only shared code is behind the scenes; your app’s back-end.

You’re essentially building a bespoke core library for your native iOS and Android apps to share.

This means all sorts of complicated business logic can be written once, instead of twice. Think of everything that goes on below an application’s UI: network calls, user input validation, data manipulation, storage and caching.

With the traditional model of separate development teams per platform, this logic is designed and implemented twice, once by an iOS team, once by an Android team. Inevitably, both will have their own quirks, their own slightly different interpretations of business requirements, and their own bugs.

Using Kotlin Multiplatform, both apps are aligned on a single standard library. This increases stability, reduces development effort and streamlines testing.

But wait, don’t other solutions provide a means of sharing UI too?

They do, and Kotlin Multiplatform steps away from this thorny issue. I won’t dive into all the pros and cons of cross-platform UI frameworks here, but it’s fair to say they all come with some amount of risk. So while some may consider this a shortcoming, Kotlin Multiplatform in fact offers a pragmatic solution for low-risk code sharing.

Code you write in a Kotlin Multiplatform library really behaves the same as equivalent code you’d write for the native platform alone. And your apps are no different from the point of view of the user.

From the developer’s perspective, the latest and greatest tools can be used to craft pixel-perfect user experiences, tailored to the platform.  Native teams can use their existing skills. And if you’re building a team, Kotlin and Android already go hand in hand.

Speaking of teams… what about the iOS developers? How did they cope with a considerable change to the regular app development workflow?

Our iOS folks all reported positive experiences with Kotlin. I think there’s a few reasons for this. For one, people really love to learn something new. New technologies, new approaches. It also brought the team closer. iOS and Android developers were collaborating, working together to create the best possible API for the shared code, that would work on both platforms.

But mainly, the benefits were easy to see by the whole team. Each new feature added to the app brought additional complex back-end logic, implemented only once. Less code to write means less code to maintain and debug in future; everyone’s happy!

Finally, and this may be controversial so I’ll whisper it, Kotlin’s actually a lot like Swift, as this cheatsheet shows! Most concepts Swift developers are used to have easily recognizable equivalents. It really isn’t difficult for an iOS team to pick up.

What is the development experience like?

Android Studio and IntelliJ are both supported for Kotlin development. This means Android developers can work entirely in one environment, but iOS developers who want to work on Kotlin code will need two IDEs side-by-side.

In fact, the story is very straightforward on Android — the shared codebase behaves like any other Kotlin library you might include in your project.

On iOS it’s also pretty simple; you build your shared Kotlin library, and then it becomes available for use in your Swift code the same as any other library you are importing.

Any class defined in your core Kotlin codebase can be accessed or instantiated from iOS or Android native code. Sticking to a pattern such as MVP keeps things tidy and organised.

What can you do in a Kotlin Multiplatform shared codebase?

The flavour of Kotlin that you write in a Kotlin Multiplatform codebase is slightly different to what you might find in an Android codebase. The main reason is that you can’t use anything provided by the JVM, or by the Android framework itself.

But fear not! Kotlin provides a rich standard library, while HTTP and JSON parsing are available via multiplatform libraries. These, combined with a growing selection of open-source libraries from the community, means that most things you’ll want to do in your iOS or Android app will be possible in Kotlin.

Of course, there is complete flexibility to fall back to native code when required. For example, in our project, the Klock library provided most of what we needed for date and time manipulation, but we still needed access to the iOS and Android native timezone utilities.

Kotlin’s native interop means it is also possible to write iOS-specific Kotlin code. This code can interact with the iOS platform APIs, meaning it is possible to write an entire iOS app only in Kotlin! While we would not recommend doing that, we did find this convenient when we needed to create very small snippets of code touching the platform APIs.

Anything to watch out for?

This technology is still emerging, so occasional issues are to be expected. And it should be noted that the iOS compatibility is still officially in beta. But, on the whole we found the stack reliable.

There is an official tutorial for getting started, along with many unofficial ones. Things tend to go well if these are followed to the letter! But if your setup has to deviate from the template for any reason, there is a very active and engaged Multiplatform community on the #kotlinlang Slack channel. This should be your first port of call in the event of any issues. The participants there have advice and solutions for most problems.

Some of the platform libraries are under heavy development, so frequent updates are available. A pragmatic approach is required to ensure that these don’t disrupt an existing, working setup.

We are very pleased with the results Kotlin Multiplatform has delivered for our teams so far. It will be at the top of our list of technologies for new projects, and we will be looking closely at deploying it into existing projects also.

Look out for more blog posts in the future which will explore the aspects of Kotlin cross-platform app development in greater depth.