Android Parcelables Made Easy

Every once in a while, I find myself having to work extensively with Parcelables. And inevitably I always find myself struggling through the process every time because of certain tiny quirks I had forgotten about. So this post is mostly a reminder for myself, but also hopefully a resource for any other Android enthusiasts.

Parcelables are usually used in places such as :

// the Bundle class implements Parcelable
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

and..

MyObject myObject = new MyObject();
Intent intent = new Intent();
intent.putExtra("myObject", myObject);
// in this case, the MyObject class has to implement Parcelable or // else we would get a compile error

To begin with, why do we have to use Parcelables in Android? Up until today, I’ve been mindlessly implementing the class without thinking twice about why we can’t just pass object references around. Some quick Googling around taught me that Android uses the customized Binder class as its IPC (interprocess communication) mechanism. This basically means that processes in Android communicate with each other using a Binder to figure out how to understand the objects being passed around.

The Parcel class is what we are familiar with as our message container. The Binder flattens the Parcel to be send, and then reconstructs the Parcel when it has been successfully transported to the receiving process.

The way the Binder knows how to “flatten” and “reconstruct” the process is through the writeToParcel method and CREATOR field that we implement when our custom objects implement the Parcelable class.

@Override
public void
writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.myInt);
dest.writeString(this.myString);
}

protected MyObject(Parcel in) {
this.myInt = in.readInt();
this.myString = in.readString();
}

public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() {
@Override
public
MyObject createFromParcel(Parcel source) {
return new MyObject(source);
}

@Override
public
MyObject[] newArray(int size) {
return new MyObject[size];
}
};

Never do this part by hand! A handy Parcelable plugin in Android Studio will do all the work for you and ensure that nothing goes wrong.

If you don’t see the Parcelable option when you click on Generate, go to Android Studio > Preferences > Plugins > Search for Parcelable > Install the Android Parcelable Code Generator.

To continue being a good Android citizen, you should next aim to write a unit test for this parcelable object to ensure that when other developers add new fields to the class they don’t break the parceling process.

@Test
public void
testParcelable() throws {
MyObject myObject = new MyObject(1, "tests are great");

Parcel parcel = Parcel.obtain();
myObject.writeToParcel(parcel, 0);

parcel.setDataPosition(0);

MyObject myObjectFromParcel = MyObject.CREATOR.createFromParcel(parcel);
assertEquals(myObject, myObjectFromParcel);
}

This is great until when the tests break and you get an error message that nobody can make sense of:

To fix this, you can auto generate a toString() method for your object like such:

At this point, if you run the test, you could end up seeing something incredibly confusing such as :

‘Expected’ value and ‘Actual’ value look exactly the same, but the test fails because we didn’t override the equals() method for MyObject. Luckily, this is another one of those methods can be auto-generated.

At this point, running the unit test will finally give us the holy green.

Another thing to note is that if MyObject contained MyOtherObject as such:

public class MyObject implements Parcelable {

private int myInt;
private String myString;
private MyOtherObject mMyOtherObject;

we would have to go through the same steps for the MyOtherObject class to generate all the methods necessary for MyOtherObject to also be properly parceled.

If you still want to know more about Parcelables and Binders, here are some other great resources:

https://guides.codepath.com/android/using-parcelable
http://elinux.org/Android_Binder
http://blog.kmckk.com/archives/3676340.html
http://stackoverflow.com/questions/3323074/android-difference-between-parcelable-and-serializable