Navigating rabbit holes and shaving yaks in mobile development: A Kotlin Multiplatform journey

Today, I want to share a tale that many of you can relate to—diving deep into rabbit holes and the infamous yak shaving sessions. Over the past two weeks, I’ve been on such a journey, experimenting with Kotlin Multiplatform (KMP) to see if it could solve some challenges we’ve been facing. So, grab your coffee, sit back, and let’s unravel this adventure together.

The problem at hand

I’m working for a client in the health and wellness space. The mobile app we’re building, originally developed in Flutter, served us well during the initial stages, but as we aimed to scale and add more complex features, Flutter began to show its limitations.

We’re dealing with heavy processing tasks and potential on-device computation, making isolates in Flutter quite a pain. So, I decided to explore KMP to see if it could be the knight in shining armour for our app. 

For those not in the know, KMP is a cross-platform application development platform. It’s relatively new and I haven’t had the chance to use it on a client project yet. And I’m going to assume you know what yak shaving is, but just in case: yak shaving refers to every little (usually seemingly unrelated) thing you have to do in order to get to the task that really needs to get done.

Diving down rabbit holes

My exploration started with a hypothesis: KMP could provide a more seamless way to handle native platform needs without the cumbersome plugin interfaces of Flutter. Inspired by the recent KotlinConf talks, I was optimistic. The promise of accessing native platforms directly, coupled with Kotlin’s growing list of cross-platform libraries, seemed like a perfect fit.

But as any seasoned developer knows, things rarely go as planned.

The yak shaving begins

The first significant hurdle was dealing with AWS Amplify for authentication. While there are native libraries for Android and Swift, KMP doesn’t support pure Swift libraries directly. This realisation led me to an extensive search for workarounds.

I toyed with various approaches:

  1. Swift-Kotlin Interop: I attempted to use a Swift-Kotlin wrapper to bridge the gap, only to find that it wouldn’t support the pure Swift Amplify library.
  2. Firebase as a Frontend: Considering Firebase Auth as an alternative, which would entail a substantial rewrite of our backend—a daunting task.
  3. KMP Cognito IDP Library: Found a promising library only to discover it was outdated and potentially abandoned.

After numerous dead ends and much frustration, I resorted to re-reading the documentation, hoping for a spark of inspiration.

A (not so) elegant solution

Finally, I concocted a rather “icky” solution. By leveraging global variables, I made the iOS app set the authentication token, which the common code could then access. It’s not pretty, and it’s definitely not something I’d want to showcase, but it worked.

This temporary fix involved setting a global value and using a listener in the iOS app to update it upon login. This way, the common code could access the token when needed. Not elegant, but functional.

Conclusions and future directions

KMP is tantalisingly close to being a game-changer. The ecosystem is growing, and the ability to write shared code for iOS and Android is a huge plus. However, until KMP supports pure Swift libraries or there’s a significant improvement in interoperability, it remains a challenge for complex, real-world applications.

The hardest part of setting up KMP is managing the dependencies and ensuring compatibility with native libraries is quite challenging. The setup involves navigating a lot of moving parts, from Kotlin to Swift to Objective-C. You need to define expected functions in common code and implement them for each platform, which can be overwhelming.

KMP allows using native views and accessing native APIs directly, which can provide a more native feel compared to Flutter’s widget-based approach. However, Flutter’s consistent experience across platforms is still a significant advantage. With KMP, you can use Multiplatform Compose, which translates to SwiftUI or Jetpack Compose, enhancing the native feel.

For now, we’ll stick with Flutter and continue to explore plugin-based solutions for the heavy lifting. The future of KMP looks promising, and I’m hopeful that with ongoing improvements, it will soon become a viable option for more demanding projects.

Final thoughts

This journey was a mix of excitement, frustration, and discovery. While we’re not ready to switch to Kotlin Multiplatform just yet, the experience has broadened our understanding and opened new possibilities for future projects. If you’re considering KMP, be prepared for some yak shaving, but know that it’s an adventure worth taking.

Want to know more about how DiUS can help you?

Offices

Melbourne
Level 3, 31 Queen St Melbourne, Victoria, 3000

Phone: 03 9008 5400

Sydney
The Commons

32 York St Sydney,

New South Wales, 2000

DiUS wishes to acknowledge the Traditional Custodians of the lands on which we work and gather at both our Melbourne and Sydney offices. We pay respect to Elders past, present and emerging and celebrate the diversity of Aboriginal peoples and their ongoing cultures and connections to the lands and waters of Australia.

Subscribe to updates from DiUS

Sign up to receive the latest news, insights and event invites from DiUS straight into your inbox.

© 2024 DiUS®. All rights reserved.

Privacy  |  Terms