Building Kotlin Multiplatform App with Compose Multiplatform

Mehmet Burak Akgün
9 min readApr 23, 2023

Howdy all, this is Burak Akgün, and I work as an Android developer. In this article, I will be sharing an example concept of a Kotlin Multiplatform app and a Compose for iOS demo. The demo will showcase how to fetch MidJourney images from a server and display them using pagination.

If you want to build something fast and easy to maintain, consider using Compose Multiplatform to build native user interfaces for Android , iOS, Desktop, and Web platforms. This lets you write code once and use it on multiple platforms, saving you time and reducing the amount of code to maintain.In this blog post, we’ll discuss setting up a Compose Multiplatform iOS project and merging Kotlin Multiplatform with Jetpack Compose for iOS.

Setting Up Environment

Of course, it is beneficial to follow along with Jetbrains’ documentation. They have explained how to install the environment very nicely, but since it is newly released, it may be necessary to deep dive into some things. First, check the installation with KDoctor.

For example, despite having XCode installed on my machine, I encountered an error for which I couldn’t find a solution in the documentation or on sites like StackOverflow. As a result, I had to search for answers on Jetbrains’ Slack channel. Luckily, someone had asked a similar question before me. I recommend this approach to everyone, as the Jetbrains team is very active in providing support on their Slack channel.

Setting Up a Compose Multiplatform iOS Project

To set up a Compose Multiplatform iOS project, you will need to install Xcode on your machine. Once you have Xcode installed, you can create a new project in Android Studio and choose “Compose Multiplatform” as the project template. For now, we can’t create Compose Multiplatform with iOS project with Android Studio wizard. But we can do it with this template https://github.com/JetBrains/compose-multiplatform-ios-android-template Within the project, you will find that the shared module contains the business logic and user interface code that is utilized by both the Android and iOS projects.

To use the shared UI module in your iOS project, add the shared module as a dependency in your Xcode project by adding it to the Podfile and running pod install. Then, you can use the shared UI code in your iOS project.

Kotlin Multiplatform and Jetpack Compose

Kotlin Multiplatform development toolkit that enables developers to write shared business logic and code across multiple platforms. Jetpack Compose is a UI toolkit for building Android apps with a declarative approach. With the new release of Compose Multiplatform, developers can now build native declarative UIs for both Android and iOS platforms from a single codebase.

By combining Kotlin Multiplatform and Jetpack Compose, developers can write shared business logic and UI code using Kotlin and create native user interfaces for both Android and iOS platforms using Compose Multiplatform. This approach can save developers a significant amount of time and reduce the amount of code that needs to be maintained.

Before this, Kotlin Multiplatform helped us with consolidation in terms of domain/data/di and shared libraries. However, with this new version, there is no longer a need to write in SwiftUI(ofc if you want, you can still write), and because this requirement has been eliminated, we can now also write fully shared ViewModels under shared/common.

Previously, whether we wrote our ViewModels in Swift or Kotlin with 3rd party libraries(like KMM-ViewModels), we had to handle observables like, @Published objects or Bindings<T> within the UIViewController on the Swift end.

MidJourney Images Compose Multiplatform Mobile Application

This application showcases stunning images created by MidJourney. It was developed using Compose Multiplatform and is compatible with Android(Wear OS, TV, Automotive, Phone, Dekstop) and iOS platforms.

You can find the application discussed in this article on GitHub at https://github.com/mbakgun/midjourney-images-compose-multiplatform

Application developed in the MVVM concept using Kotlin and Jetpack Compose. Network request states, endless pagination, image loading, and image caching processes were performed.

Consumer apps do not have any complex structures or operations. They use the common UI layer (including ViewModel) and are responsible for creating MjImagesApp. MjImagesApp and the dependency of this Composable, MjImagesViewModel, works as same on Android and iOS platforms.

Design

The MidJourney Images Compose Multiplatform Mobile Application follows a clean architecture pattern, with a clear separation between UI, domain, and data layers. The application uses Kotlin Coroutines for asynchronous programming and Ktor for networking. The data layer is responsible for fetching images from the server, and the domain layer handles pagination and filtering(mapping). The UI layer is built using Jetpack Compose and is responsible for displaying the images to the user.

Overall, the architecture of the application promotes maintainability, testability, and scalability.

Libraries

- [Ktor](https://ktor.io/)
- [Koin](https://insert-koin.io/)
- [Kotlinx Serialization](https://kotlinlang.org/docs/serialization.html)
- [Kotlinx Coroutines](https://kotlinlang.org/docs/coroutines-overview.html)
- [Compose ImageLoader](https://github.com/qdsfdhvh/compose-imageloader)
- [KMM-ViewModel](https://github.com/rickclephas/KMM-ViewModel)
- [Multiplatform Settings](https://github.com/russhwolf/multiplatform-settings)

Ktor is a web framework for Kotlin that provides a client and server API for building asynchronous servers and clients in connected systems. It was used in the MidJourney Images Compose Multiplatform Mobile Application for networking purposes.

Koin is a lightweight dependency injection framework for Kotlin that helps in building better applications. It was used in the application to provide a dependency injection mechanism that could be used across multiple platforms.

Kotlinx Serialization is a Kotlin library that provides a way to convert Kotlin objects to and from JSON format. It was used in the application to serialize and deserialize JSON data.

Kotlinx Coroutines is a library for asynchronous programming in Kotlin. It was used in the application to provide concurrency and to handle multiple tasks at once. It helps to improve performance and reduce the blocking of threads.

Compose ImageLoader is a library that provides an easy way to load images in Jetpack Compose. It was used in the application to load images from a server and display them to the user. Also, it provides us extensive caching mechanisms. Also, Compose ImageLoader works with Kotlin Coroutines.

KMM-ViewModel is a library that provides a way to share ViewModels between Android and iOS platforms in Kotlin Multiplatform Mobile. It was used in the application to write ViewModels that could be shared between the Android and iOS platforms.

In summary, the libraries used in the MidJourney Images Compose Multiplatform Mobile Application were carefully selected to ensure the proper functioning of the application.

Tests

The unit tests for the shared/common code can be run under the shared/common folder. The unit tests written for this project are located in this directory. The Compose UI tests, on the other hand, were added under the androidTests folder. If there is platform-specific logic in the iOS and Android front end, it makes sense, and is necessary to test it separately. The Maestro tests are written under the maestro package.

Limitations

  1. One major challenge of building a previosly(Kotlin Multiplatform Mobile (KMM)) now Kotlin Multiplatform application is ensuring that all libraries used in the project support building on both iOS and JVM platforms (if you decide to use them in common/shared). This is because a library must be buildable on both platforms to be used in the common path. If a library cannot be built on iOS, it cannot be used in the common path. However, the Kotlin Multiplatform ecosystem is rapidly growing, and the number of Kotlin Multiplatform-supported libraries and tools that can be used is increasing day by day. As a result, it is becoming easier to find libraries that support both iOS and JVM platforms and to build high-quality Kotlin Multiplatform applications. In cases where a library cannot be built on iOS, it is still possible to use it in a Kotlin Multiplatform application by using expect/actual under shared/android or shared/ios instead of in the common path. This allows developers to continue using a library that is critical for their application, while still building a high-quality Kotlin Multiplatform application.
  2. You may have noticed a slight visual difference between the Android and iOS applications. This difference is due to my use of LazyVerticalStaggeredGrid for Android and LazyVerticalGrid for iOS. During the build process, I encountered an issue that I was not able to resolve as of today. Specifically, I was not able to use LazyStaggeredGrid for Jetpack Compose for iOS.

Such small situations can always occur for a framework that is in alpha version. And this blocker has opened up a nice area for the use of expect/actual functions, which were introduced with Kotlin Multiplatform.

As a small note, the fix for this issue will be available soon. I had contacted Dima Avdeev [JetBrains] via Slack and thanks him for the quick action.

Update : Thanks to the team, it was fixed.

Recently added support for Android Automotive

Conclusion

I have thoroughly tested the MidJourney Images Compose Multiplatform Mobile Application on my physical iPhone device, and I am happy to report that I did not encounter any performance issues. The application ran smoothly, and I was able to navigate through the app without any lags or delays.

Furthermore, it is worth noting that the Kotlin code used in the application is transformed into Objective-C by the compiler. This allows the code to be executed natively on iOS devices, ensuring optimal performance and compatibility.

In conclusion, Compose Multiplatform is an excellent tool for building native user interfaces for both Android and iOS platforms from a single codebase. By combining Kotlin Multiplatform and Jetpack Compose, developers can write shared business logic and UI code using Kotlin and create native user interfaces for both platforms using Compose Multiplatform. This approach can save developers a significant amount of time and reduce the amount of code that needs to be maintained.If you are looking for a way to build native UIs for both Android and iOS platforms, Compose Multiplatform is definitely worth considering. Although it is currently in alpha and has some limitations, it will become very good with both the support of the open-source community and the version improvements of the JetBrains team in the future.

Lastly, it is worth noting that in a Kotlin Multiplatform project, sharing common composables on the UI side is much easier with other Android platforms such as Android Automotive, Wear OS, Android TV, Desktop, and Web.

This project has web support and if you want to test the ‘Compose for Web (JS)’ in your browser, please open the demo.

Recently I’ve added WASM support, you can also check the WASM demo.

Thanks for your time 🌸 That's all 🙏
Happy Kotlin / Compose

--

--

Mehmet Burak Akgün

Senior Android Developer at Trendyol International @Berlin