Parcelable

General Description

An object that implements the Parcelable interface can be “flattened” for inter-process communication or, as is the case most of the time when I use it, for placing in a Bundle (which is a Java associative array or dictionary).

The documentation makes this seem a lot harder than it is. The sample code from the documentation pretty much covers it.

Implementation

1. Implement the Parcelable interface

public class MyClass implements Parcelable
    ...
    @Override
    public int describeContents()
        {
        // From what I've read on the Web, this function should always 
        // return this value. The documentation is very, very vague. I 
        // think this value is actually used only when the parcel really 
        // is a file descriptor.

        // return CONTENTS_FILE_DESCRIPTOR;

        // The sample in the documentation for a general object like mine
        // just returns 0 here.

        return 0;
        }

    @Override
    public void writeToParcel(Parcel dest, int flags)
        {
        // Order is important. The order here should be the same as the
        // is expected in the constructor

	// It sometimes comes in handy to write arrays of values. The 
        // syntax looks like this:

        dest.writeIntArray(new int[] {publisherID, bookID, section});
        dest.writeStringArray(new String[] {verseReference, anchor, TOCPath});
        dest.writeBooleanArray(new boolean[] {wasHyperlink, noHistory});
        }

2. Implement the CREATOR field

Again, the documentation is weirdly vague, but here’s what it looks like. Yours can look identical to this with the exception of “MyClass”, which is the name of your class:

    public static final Parcelable.Creator CREATOR = 
        new Parcelable.Creator() 
        {
        public MyClass createFromParcel(Parcel in) 
            {
            // Calls our constructor that takes a Parcel

            return new MyClass(in); 
            }

        public MyClass[] newArray(int size) 
            {
            return new MyClass[size];
            }
        };

3. Implement a constructor that takes a Parcel

The parcel will have been created with your writeToParcel() method, so it should read values back from the parcel in the same order that you wrote them out:

    public MyClass(Parcel in)
        {
        // Since we used some arrays to demonstrate the writeToParcel()
        // method, read them back here in the same order.

        int [] intData = new int[3];
        in.readIntArray(intData);
        publisherID = intData[0];
        bookID = intData[1];
        section = intData[2];

        String [] stringData = new String[3];
        in.readStringArray(stringData);
        verseReference = stringData[0];
        anchor = stringData[1];
        TOCPath = stringData[2];

        boolean [] booleanData = new boolean[2];
        in.readBooleanArray(booleanData);
        wasHyperlink = booleanData[0];
        noHistory = booleanData[1];
        }

Putting a Parcel in a Bundle

I often use Parcelable objects as parameters to an Intent:

    // Create the parameter object

    MyClass param = new MyClass();

    // Load it up

    param.publisherID = 3;
    param.bookID = 4;
    param.verseReference = "John 3:16";
    // etc.

    // Create the intent

    Intent intent = new Intent("com.laridian.pocketbible.DOSOMETHING");

    // Put the flattened parameter in the Intent and broadcast it

    intent.putExtra(getString(R.string.someparam), (Parcelable) param);
    sendBroadcast(intent);

Retrieving a Parcel from a Bundle

Retrieving the flattened object is no different than retrieving any other object from the Bundle. It will be un-parceled by the cast:

    MyClass reconstructedObject =
        (MyClass) intent.getExtras().getParcelable(context.getString(R.string.someparam));

Don’t store Parcels!

Parcels are not meant to be persistent. They are meant to have short lives, since the format could change between releases of the API/SDK/JRE. Don’t store them anywhere.

Leave a Reply

Your email address will not be published. Required fields are marked *