How to use Parcelable and custom @TypeParceler with Kotlin Multiplatform Mobile (KMM)
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
:
**IMPORTANT NOTE**: You must import
kotlinx.parcelize.*
**NOT**kotlinx.android.parcel.*
!!!
in androidMain/…/Platform.kt
:
in iosMain/…/Platform.kt
:
Here is an example domain class that will be shared by both iOS and Android:
in ../shared/commonMain/…/domain/note/Note.kt
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