Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parcelable and Inheritance

This has been asked a few times here on SO, but my case is a bit different.

I have class A that implements Parcelable. Class A contains some member data that can be parceled. It has its own CREATOR and implements writeToParcel(), describeContents(), and a constructor that accepts a Parcel.

There is class B that extends from class A. Class B has additional member data, but none of them need to be parceled. Basically, class B's parcelable data is the same as class A. If I try to put B in a Bundle, pass it to another Activity, and read it back, I would get a ClassCastException. I guess that's expected.

After a bit of trial-and-error, in order to make class B parcelable, I have to implement at least these two things:

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

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

public B(Parcel in) throws JSONException {
    super(in);
}

So my concern is this. There are about half a dozen or more classes that extend from A and all have the same issue as B. It seems silly that each one of them has to add their own static CREATOR and a constructor that accepts a Parcel, only to pass it back to A. Everything else is identical. The only thing that makes it different is the name of the class. It beats the purpose of having inheritance in the first place.

For example, if there's another class C that extends B, I need to do the same:

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

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

public C(Parcel in) throws JSONException {
    super(in);
}

Is there some sort of clever techniques in Java to automate this process? Perhaps using generic of some sort? If there's no other way, I might just as well just remove the inheritance lineage, and require each class to implement Parcelable themselves.

like image 712
garbagecollector Avatar asked Oct 09 '12 23:10

garbagecollector


People also ask

What does Parcelable mean?

A Parcelable is the Android implementation of the Java Serializable. It assumes a certain structure and way of processing it. This way a Parcelable can be processed relatively fast, compared to the standard Java serialization.

What is the use of Parcelable?

Parcelable and Bundle objects are intended to be used across process boundaries such as with IPC/Binder transactions, between activities with intents, and to store transient state across configuration changes.

What is Parcelable data?

Parcelable is a serialization mechanism provided by Android to pass complex data from one activity to another activity.In order to write an object to a Parcel, that object should implement the interface “Parcelable“.

How do you implement Parcelable?

Create Parcelable class without plugin in Android Studioimplements Parcelable in your class and then put cursor on "implements Parcelable" and hit Alt+Enter and select Add Parcelable implementation (see image). that's it.


1 Answers

This is a little complicated, but the only way I can think of offhand involves reflection - Provided all of the subclasses have a constructor that takes a Parcel that then calls super(parcel), you could make the class name a part of the parcel - then in your createFromParcel method of A:

public A createFromParcel(Parcel source) {
    Class clazz = Class.forName(source.readString());
    Class[1] paramTypes = { Parcel.class }; 
    Constructor ctor = clazz.getConstructor(paramTypes);
    A myA = (A) ctor.newInstance(source);
    return myA;
}

Note that this was written largely off the cuff and may need some tweaking before it runs (I know for sure it's missing checked exception handlers) - but hopefully the idea is clear

like image 177
JRaymond Avatar answered Oct 15 '22 12:10

JRaymond