How to use Parcelable and custom @TypeParceler with Kotlin Multiplatform Mobile (KMM)

Chris Athanas
2 min readOct 14, 2022
Photo by Kenny Eliason on Unsplash

Cross platform annotations are rather confusing at first glance!

This short article shows you how to work with KMM (Kotlin Multiplatform Mobile) cross-platform annotations, implement a custom @TypeParceler for Android Parcelable interface in a KMM project for any Type or Class including primitives.

It shows proper use of Annotations, Interfaces, Generics, Objects, @TypeParceler, Parceler ,Parcelable, Parcelize and how to implement each platform’s common code, specifically for iOS and Android.

The biggest hurdle in implementing cross-platform entities in KMM is properly defining the annotations and setting up the implementation and the “stubs” for each platform. Code needs to be implemented on one platform and ignored on the other platform.

I will show how to implement the Parcelable interface for Android, and stub the Parcelable interface for iOS (so it is properly ignored), as iOS does not need or useParcelable.

In this example, I will use the non-natively parcelable class of LocalDateTime , from the shared Kotlin-native kotlinx-datetime library, as the example of non-primitive ‘Parcelable’ class. After seeing this example, its straightforward to use any non-primitive class, just change the implementation and add the appropriate @TypeParceler .

On Android, this code is very necessary to prevent crashes when the Android app is put into the background, as the Parceler is automatically run (on Android) to save state. Without this implementation, your app will crash when your domain models have custom class types. The iOS platform does not use a Parceler , so it needs to be stubbed out.

Using primitive data types is rather straightforward as you only stub/implement the Parcelable interface and the @Parcelize annotation.

In this article I go a step further and show you how to implement a custom@TypeParceler to use a non-primitive class Parceler. In this example we are making a @TypeParceler for LocalDateTime.

in build.gradle.kts(:shared) :

in commonMain/…/Platform.kt :

The CommonMain annotations that will be overridden for each platform, ie: implemented on Android and ignored on iOS.

**IMPORTANT NOTE**: You must import kotlinx.parcelize.*
**NOT** kotlinx.android.parcel.* !!!

in androidMain/…/Platform.kt :

This is the Android code that will implement the custom @TypeParceler, @Parcelize and the Parcelable interface.

in iosMain/…/Platform.kt :

These are the iOS “stubs” that will be ignored by the iOS side, as iOS does not use Parcels.

Here is an example domain class that will be shared by both iOS and Android:

in ../shared/commonMain/…/domain/note/Note.kt

Note, even though both platforms will see this code, the “Common” parts will be defined differently for each platform. The Android code will see the Parcel implementations and the iOS code will see the “stubs”, ie: nothing.

Given this code example you are able to readily extend it for any custom type that needs to use @Parcelize, as well as implement cross platform annotations for other parts of Android and iOS code.

I attempted to implement the @RawValue but its not documented (AFAIK) and the above method of using @TypeParceler works very well for any particular non-primitive class. I leave that as an exercise for you!

Sample project showing full implementation: https://github.com/realityexpander/NoteAppKMM

Join the KMP Developers Group: Twitter/X: https://twitter.com/i/communities/1739883885658607808 FaceBook: https://www.facebook.com/groups/913147236893976 LinkedIn: https://www.linkedin.com/groups/14367209

--

--

Chris Athanas

KMP (Kotlin Mutli-Platform) Android+iOS+Web Developer, Based out of Austin, TX and Tepoztlán, Mexico