Skip to content
Daniel Bergløv edited this page Nov 8, 2015 · 2 revisions

Back to Home


UtilsLib packs 3 helper classes that can be used when creating Parcelable/JSONParcelable objects, MultiParcelable, MultiParcelableBuilder and ParcelHelper.

MultiParcelable

This is an interface that includes both JSONParcelable and Parcelable interfaces. The interface also includes MultiParcelable$MultiCreator and MultiParcelable$MultiClassLoaderCreator interfaces to use when creating the CREATOR field.

MultiParcelableBuilder

This is a class implementing the MultiParcelable interface. It also packs a ready-to-use CREATOR derived from MultiParcelable$MultiClassLoaderCreator that uses reflection to automatically locate and create classes when unparceling and it includes the tools from ParcelHelper. This class makes it extremely fast and simple to create new Parcelable/JSONParcelable objects by extending from this.

ParcelHelper

Android Parcel is a great idea. Sadly it is poorly build and includes a lot of bugs/issues. For one it's writeValue has been build to check for List, Map etc. before checking for Parcelable, which means that you can run into problems when using custom made Parcelable versions of the Collection classes. It's internal handling of List and Map is also very flawed, for not to mentioned the ClassLoader issues because earlier Android version does not parse the ClassLoader used at the beginning.

The ParcelHelper class can help with all of this by simply using it's parcelData and unparcelData. And if you make sure to use the MultiParcelable$MultiClassLoaderCreator interface for your CREATOR, it will also take care of the ClassLoader issue on all Android versions.

Example 1

public class MyClass extends MultiParcelableBuilder {

    Parcelable mParcObject;
    JSONParcelable mJParcObject;

    public MyClass(JSONParcel in, ClassLoader loader) {
        mJParcObject = in.readJSONParcelable(loader);
    }

    public MyClass(Parcel in, ClassLoader loader) {
        mParcObject = unparcelData(in, loader);
    }

    @Override
    public void writeToJSON(JSONParcel dest) throws JSONException {
        super.writeToJSON(dest);

        dest.writeJSONParcelable(mJParcObject);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);

        parcelData(mParcObject, dest, flags);
    }
}

Example 2

If you can't extend the class due to that your class already derives from another class, it can still be quite simply to implement.

public class MyClass extends MyParentClass implements MultiParcelable {

    // Simply reuse the creator from MultiParcelableBuilder
    public static MultiCreator CREATOR = MultiParcelableBuilder.CREATOR;

    Parcelable mParcObject;
    JSONParcelable mJParcObject;

    public MyClass(JSONParcel in, ClassLoader loader) {
        mJParcObject = in.readJSONParcelable(loader);
    }

    public MyClass(Parcel in, ClassLoader loader) {
        // Now we just need to access ParcelHelper directly
        mParcObject = ParcelHelper.unparcelData(in, loader);
    }

    @Override
    public void writeToJSON(JSONParcel dest) throws JSONException {
        dest.writeString(getClass().getName());
        dest.writeJSONParcelable(mJParcObject);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // We need to write the class name as it is used by the creator
        dest.writeString(getClass().getName());
        ParcelHelper.parcelData(mParcObject, dest, flags);
    }
}

Example 3

Or you can make your own CREATOR

public class MyClass extends MyParentClass implements MultiParcelable {

    public static MultiCreator<MyClass> CREATOR = new MultiClassLoaderCreator<MyClass>() {
        @Override
        public T createFromParcel(Parcel source) {
            return new MyClass(source, ClassLoader.getSystemClassLoader());
        }

        @Override
        public MyClass createFromParcel(Parcel source, ClassLoader classLoader) {
            return new MyClass(source, classLoader);
        }

        @Override
        public MyClass createFromJSON(JSONParcel source, ClassLoader loader) {
            return new MyClass(source, classLoader);
        }

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

    Parcelable mParcObject;
    JSONParcelable mJParcObject;

    public MyClass(JSONParcel in, ClassLoader loader) {
        mJParcObject = in.readJSONParcelable(loader);
    }

    public MyClass(Parcel in, ClassLoader loader) {
        // Now we just need to access ParcelHelper directly
        mParcObject = ParcelHelper.unparcelData(in, loader);
    }

    @Override
    public void writeToJSON(JSONParcel dest) throws JSONException {
        dest.writeJSONParcelable(mJParcObject);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        ParcelHelper.parcelData(mParcObject, dest, flags);
    }
}

Clone this wiki locally