-
Notifications
You must be signed in to change notification settings - Fork 1
MultiParcelable
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);
}
}