I finally had the time to dive into Compose Multiplatform - and this was also my first experience with Kotlin Multiplatform. I'll share my first impressions from using this technology in this blog post.
Some words from my background: I'm an Android developer who's confident with Kotlin and Compose. I've been working with different languages and frameworks before switching to Android development, so I could say learning new things is easy. However, I've never done any iOS development, so that part is entirely new to me.
The app I'm working with is currently just UI, and I have yet to dive into any architectural components, such as working with databases or view models. So, that's the context for these thoughts, and it's likely that once I get deeper into the development and concepts, I'll have more opinions and thoughts.
The App I'm Building
The moment I started writing the blog post, I realized that it might be helpful to talk about the app I'm building here. So here we go.
It's an app version of neule.art, a color picker for knitted sweaters I created a few years ago. In the first version, there's just the picture of the sweater (the same as on the website) and modals opening for choosing the color from the list of colors. The colorways are based on the colors of Istex Lettlopi, a yarn often used for Icelandic sweaters.
When I created the website, I hand-drew the picture on top of an image of my friend wearing a sweater and then turned it into an SVG. In the app, I used Canvas to replicate the illustration. Here's what the app looked like at one point of development:
Now that you have an idea of what I was building, let's get into my thoughts about Compose Multiplatform.
Some Things Just Work
After I had created the first version of the app, there was one thing I was really surprised about: On the UI level, things just worked.
One of these working things was the illustration. I first drafted the illustration for another project with Compose (as part of my explorations with Canvas) and wanted to port it to a Kotlin Multiplatform app. What did I do? I copy-pasted the code and built it, and it just worked on both Android and iOS. I don't know why, but I expected some problems at that point.
Other UI components I used at this point also just worked. Sure, I was building with the familiar elements, so everything looked like Android apps, even on iOS, but nothing crashed. I could run the application on both platforms.
Once I ensured nothing crashed, I wanted to make the color picker modals more native-like for iOS. That leads to the next thing I realized - there aren't that many resources available yet.
Lack of Resources
So, when I started investigating how to create the iOS-like color picker, I did not find that much material out there. Yes, there are the official docs (both for Compose Multiplatform and for iOS), but I feel like as someone who has never done iOS development, the bridge between these concepts is still missing. The technology is still so new and evolving, that there are a lot of blank spots, and it can be hard to find any blog posts, videos, or any other resources to understand how to apply the basic concepts to action.
And this is normal for new technologies - it takes time to build the community, and for developers to experiment and find these things, and start writing about more complex use cases. That's something I've seen with Android accessibility topics as well.
In this particular case, if I had more experience with iOS development, I think I could apply that knowledge pretty straightforwardly. But I don't, so it will take time, asking around from more knowledgeable people, and some trial and error. And once I get there, I will, naturally, create some of those resources I'm looking for now.
Also, it's worth noting that Compose Multiplatform for iOS is still in Beta, so it's also natural that there aren't too many resources around.
However, not everything is lacking resources. Some things are documented well, and I really enjoyed learning about the expect / actual -pattern used to bridge the gap between native implementations and shared code. Let's talk about that next.
Expect / Actual Pattern is Awesome
So, in Kotlin (and Compose) Multiplatform, shared code is written for all platforms, and platform-specific code can be written for individual platforms. It also has this pattern to write a function in the shared code, annotate it with expect
, and then create the actual implementations in native platform code to work in different environments. And I love it.
I think these kinds of patterns make multiplatform development a compelling option when you can actually write the code for the platforms in native languages if needed. It also allows flexibility - if some shared implementation doesn't work, or if you want to build apps to match the expected experiences on different platforms, it's possible this way.
I am comparing this experience with coding with React Native and using apps that have been coded with React Native, and I am excited. I keep telling everyone that switching to Android and Kotlin from JavaScript (and TypeScript) has been the one thing that has improved my life quality, and being able to build cross-platform apps with Kotlin is just awesome.
In addition, with Kotlin and Compose Multiplatform, maybe the apps would not always look like iOS apps. For some reason, all the React Native apps I've used are more iOS-y than I'd like to see on my Android device.
Wrapping Up
So, all in all, my experiences with Compose Multiplatform (and Kotlin Multiplatform) have been positive so far. I recognize that the technology is still evolving, but I see a lot of potential for streamlining app development. As an Android developer, I really hope that it will get adopted more and more. I enjoy building apps with Kotlin.