Since Kotlin 1.1.4, the Kotlin Android Extensions was updated with a new experimental feature, replacing the boilerplate-ridden way of implementing a Parcelable interface with an annotation. Since then, the 1.1.6 release added IDE support - but what is a Parcelable, and why should you use it?

What's a Parcelable?

Parcelable is an Android-specific interface, created to be far more efficient than Serializable, and also to fix problems around regular Java serialization. It is not used exclusively on Android, though. A couple of platform-related features (like Binders and AIDL) work only with Parcelable objects, others support both serializable and parcelable (for example adding extras to a Bundle or Intent) objects.

Not to confuse with Serializable, which is a standard Java interface. Used for Intents, and passing data between components of the app, or between multiple apps. You simply mark a class Serializable by implementing the interface, and Java will automatically serialize it in certain situations. But simplicity has its cost: this approach uses reflection, creates a lot of temporary objects, and causes GC.

This is where Parcelable takes the crown - instead of using reflection, one has to implement serialization by hand, making it more efficient, and run significantly faster. A huge drawback is of course that that this means quite a few extra lines of boiler plate. Also, it is hard to maintain: modifying a class requires updating the implemented functions as well. The following example illustrates how to make a simple model class parcelable.

public class Book implements Parcelable { public String title; public String author; public int year; public Book(final String title, final String author, final int year) { this.title = title; this.author = author; this.year = year; } private Book(Parcel in) { this.title = in.readString(); this.author = in.readString(); this.year = in.readInt(); } public static final Creator<Book> CREATOR = new Creator<Book>() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(title); parcel.writeString(author); parcel.writeInt(year); } }

Quite the boilerplate! Also, writing this by hand is very error-prone: adding a new class variable requires modifying multiple functions manually.

The Kotlin way

The Kotlin Android Extensions is usually used for eliminating findViewById() calls, the 1.1.4 release extended it with an experimental feature for simplifying Parcelable implementation into using an annotation. Hence the experimental label, it is necessary to add the following statement to the build script:

androidExtensions { experimental = true }

So the class above translates to this:

@Parcelize class Book(val title: String, val author: String, val year: Int) : Parcelable

Sidenote: the compiler will warn that This class implements Parcelable but does not provide a CREATOR field - the @SuppressLint("ParcelCreator") annotation fixes this.

Taking a look at decompiled bytecode (with @Metadata annotations omitted, for clarity) shows that a standard parcelable class is generated.

public final class Book implements Parcelable { @NotNull private final String title; @NotNull private final String author; private final int year; public static final Book.Creator CREATOR = new Book.Creator(); @NotNull public final String getTitle() { return this.title; } @NotNull public final String getAuthor() { return this.author; } public final int getYear() { return this.year; } public Book(@NotNull String title, @NotNull String author, int year) { Intrinsics.checkParameterIsNotNull(title, "title"); Intrinsics.checkParameterIsNotNull(author, "author"); super(); this.title = title; this.author = author; this.year = year; } public final int describeContents() { return 0; } @AvoidUninitializedObjectCopyingCheck public final void writeToParcel(@NotNull Parcel parcel, int flags) { Intrinsics.checkParameterIsNotNull(parcel, "parcel"); parcel.writeString(this.title); parcel.writeString(this.author); parcel.writeInt(this.year); } public static class Creator implements android.os.Parcelable.Creator { @NotNull public final Book[] newArray(int size) { return new Book[size]; } @NotNull @AvoidUninitializedObjectCopyingCheck public final Object createFromParcel(@NotNull Parcel in) { Intrinsics.checkParameterIsNotNull(in, "in"); return new Book(in.readString(), in.readString(), in.readInt()); } } }

Enums, sealed classes, and classes as referenced class variables also work, given that their concrete implementation is parcelable as well.

The bottom line is Parcelable is super fast, and every Android developer should use it instead of Serializable objects, where applicable. Even though traditionally it does require some boilerplate code and extra development time, Kotlin Android Extensions reduces this to the use of a single annotation. In a way, it is similar to data classes, as in instead of writing boilerplate code, the same functionality is achieved with a single keyword.