Parcelable implementation generator

The kotlin-parcelize plugin provides a Parcelable implementation generator.

To include support for Parcelable, add the Gradle plugin to your app's build.gradle file:

Groovy

plugins{
id'kotlin-parcelize'
}

Kotlin

plugins{
id("kotlin-parcelize")
}

When you annotate a class with @Parcelize, a Parcelable implementation is automatically generated, as shown in the following example:

importkotlinx.parcelize.Parcelize
@Parcelize
classUser(valfirstName:String,vallastName:String,valage:Int):Parcelable

@Parcelize requires all serialized properties to be declared in the primary constructor. The plugin issues a warning on each property with a backing field declared in the class body. Also, you can't apply @Parcelize if some of the primary constructor parameters are not properties.

If your class requires more advanced serialization logic, write it inside a companion class:

@Parcelize
dataclassUser(valfirstName:String,vallastName:String,valage:Int):Parcelable{
privatecompanionobject: Parceler<User>{
overridefunUser.write(parcel:Parcel,flags:Int){
// Custom write implementation
}
overridefuncreate(parcel:Parcel):User{
// Custom read implementation
}
}
}

Supported types

@Parcelize supports a wide range of types:

  • Primitive types (and their boxed versions)
  • Objects and enums
  • String, CharSequence
  • Duration
  • Exception
  • Size, SizeF, Bundle, IBinder, IInterface, FileDescriptor
  • SparseArray, SparseIntArray, SparseLongArray, SparseBooleanArray
  • All Serializable (including Date) and Parcelable implementations
  • Collections of all supported types: List (mapped to ArrayList), Set (mapped to LinkedHashSet), Map (mapped to LinkedHashMap)
    • Also a number of concrete implementations: ArrayList, LinkedList, SortedSet, NavigableSet, HashSet, LinkedHashSet, TreeSet, SortedMap, NavigableMap, HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap
  • Arrays of all supported types
  • Nullable versions of all supported types

Custom Parcelers

If your type is not supported directly, you can write a Parceler mapping object for it.

classExternalClass(valvalue:Int)
objectExternalClassParceler:Parceler<ExternalClass>{
overridefuncreate(parcel:Parcel)=ExternalClass(parcel.readInt())
overridefunExternalClass.write(parcel:Parcel,flags:Int){
parcel.writeInt(value)
}
}

You can apply external parcelers using @TypeParceler or @WriteWith annotations:

// Class-local parceler
@Parcelize
@TypeParceler<ExternalClass,ExternalClassParceler>()
classMyClass(valexternal:ExternalClass):Parcelable
// Property-local parceler
@Parcelize
classMyClass(@TypeParceler<ExternalClass,ExternalClassParceler>()valexternal:ExternalClass):Parcelable
// Type-local parceler
@Parcelize
classMyClass(valexternal:@WriteWith<ExternalClassParceler>()ExternalClass):Parcelable

Create data from Parcel

In Java code, you can access the CREATOR field directly.

class UserCreator{
staticUserfromParcel(Parcelparcel){
returnUser.CREATOR.createFromParcel(parcel);
}
}

In Kotlin, you can't use the CREATOR field directly. Instead, use kotlinx.parcelize.parcelableCreator.

importkotlinx.parcelize.parcelableCreator
funuserFromParcel(parcel:Parcel):User{
returnparcelableCreator<User>().createFromParcel(parcel)
}

Skip properties from serialization

If you want to skip some property from being parcelized, use the @IgnoredOnParcel annotation. It can also be used on properties within a class's body to silence warnings about the property not being serialized. Constructor properties annotated with @IgnoredOnParcel must have a default value.

@Parcelize
classMyClass(
valinclude:String,
// Don't serialize this property
@IgnoredOnParcelvalignore:String="default"
):Parcelable{
// Silence a warning
@IgnoredOnParcel
valcomputed:String=include+ignore
}

Use android.os.Parcel.writeValue for serializing a property

You can annotate a type with @RawValue to make Parcelize use Parcel.writeValue for that property.

@Parcelize
classMyClass(valexternal:@RawValueExternalClass):Parcelable

This might fail at runtime if the value of the property is not natively supported by Android.

Parcelize might also require you to use this annotation when there is no other way to serialize the property.

Parcelize with sealed classes and sealed interfaces

Parcelize requires a class to parcelize to not be abstract. This limitation does not hold for sealed classes. When the @Parcelize annotation is used on a sealed class, it does not need to be repeated for the deriving classes.

@Parcelize
sealedclassSealedClass:Parcelable{
classA(vala:String):SealedClass()
classB(valb:Int):SealedClass()
}
@Parcelize
classMyClass(vala:SealedClass.A,valb:SealedClass.B,valc:SealedClass):Parcelable

Setup Parcelize for Kotlin multiplatform

Prior to Kotlin 2.0, you could use Parcelize by aliasing Parcelize annotations with expect and actual:

// Common code
packageexample
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
expectannotationclassMyParcelize()
expectinterfaceMyParcelable
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
expectannotationclassMyIgnoredOnParcel()
@MyParcelize
classMyClass(
valx:String,
@MyIgnoredOnParcelvaly:String=""
):MyParcelable
// Platform code
packageexample
actualtypealiasMyParcelize=kotlinx.parcelize.Parcelize
actualtypealiasMyParcelable=android.os.Parcelable
actualtypealiasMyIgnoredOnParcel=kotlinx.parcelize.IgnoredOnParcel

In Kotlin 2.0 and higher, aliasing annotations that trigger plugins is unsupported. To circumvent this, provide a new Parcelize annotation as the additionalAnnotation parameter to the plugin instead.

// Gradle build configuration
kotlin{
androidTarget{
compilerOptions{
// ...
freeCompilerArgs.addAll("-P","plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=example.MyParcelize")
}
}
}
// Common code
packageexample
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
// No `expect` keyword here
annotationclassMyParcelize()
expectinterfaceMyParcelable
@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
expectannotationclassMyIgnoredOnParcel()
@MyParcelize
classMyClass(
valx:String,
@MyIgnoredOnParcelvaly:String=""
):MyParcelable
// Platform code
packageexample
// No typealias for MyParcelize here
actualtypealiasMyParcelable=android.os.Parcelable
actualtypealiasMyIgnoredOnParcel=kotlinx.parcelize.IgnoredOnParcel

Because the Parcel interface is only available on Android, Parcelize won't generate any code on other platforms, so any actual implementations there can be empty. It is also not possible to use any annotation that requires referencing the Parcel class, for example @WriteWith, in common code.

Experimental features

Data class serializer

Available since Kotlin 2.1.0.

The DataClass annotation allows for serializing data classes as if they were themselves annotated with Parcelize. This annotation requires the kotlinx.parcelize.Experimental opt-in.

@file:OptIn(kotlinx.parcelize.Experimental::class)
dataclassC(vala:Int,valb:String)
@Parcelize
classP(valc:@DataClassC):Parcelable

The primary constructor and all of its properties must be accessible from the Parcelable class. Additionally, all primary constructor properties of the data class must be supported by Parcelize. Custom Parcelers, if chosen, should be specified on the Parcelable class, not the data class. If the data class implements Serializable at the same time, the @DataClass annotation takes priority: android.os.Parcel.writeSerializable won't be used.

A practical use case for this is serializing kotlin.Pair. Another useful example is simplifying multiplatform code: common code could declare the data layer as data classes, which Android code could then augment with serialization logic, removing the need for Android-specific annotations and type aliases in common code.

// Common code:
dataclassMyData(valx:String,valy:MoreData)
dataclassMoreData(vala:String,valb:Int)
// Platform code:
@OptIn(kotlinx.parcelize.Experimental::class)
@Parcelize
classDataWrapper(valwrapped:@DataClassMyData):Parcelable

Non val or var parameters in primary constructor

Available since Kotlin 2.1.0.

To enable this feature add experimentalCodeGeneration=true to the parcelize plugin arguments.

kotlin{
compilerOptions{
// ...
freeCompilerArgs.addAll("-P","plugin:org.jetbrains.kotlin.parcelize:experimentalCodeGeneration=true")
}
}

This feature lifts the restriction on primary constructor arguments having to be val or var. This solves one pain point of using parcelize with inheritance, which earlier required using open properties.

// base parcelize
@Parcelize
openclassBase(openvals:String):Parcelable
@Parcelize
classDerived(
valx:Int,
// all arguments have to be `val` or `var` so we need to override
// to not introduce new property name
overridevals:String
):Base(s)
// experimental code generation enabled
@Parcelize
openclassBase(vals:String):Parcelable
@Parcelize
classDerived(valx:Int,s:String):Base(s)

Such parameters are only allowed to be used in arguments to the base class constructor. Referencing them in the body of the class is not allowed.

@Parcelize
classDerived(s:String):Base(s){// allowed
@IgnoredOnParcel
valx:String=s// ERROR: not allowed.
init{
println(s)// ERROR: not allowed
}
}

Feedback

If you encounter any issues with the kotlin-parcelize Gradle plugin, you can file a bug.

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026年03月06日 UTC.