I have a class that implements Parcelable
interface:
class A implements Parcelable {
}
I have another class B
th
A better way to handle this that avoids reflexion would be to simply call the static creator in the target type like this:
this.amazingObject = AmazingObject.CREATOR.createFromParcel(in);
and write it to the Parcelable
using this.amazingObject.writeToParcel(Parcel, int)
Internally, when calling readParcelable(ClassLoader)
this happens:
public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
Parcelable.Creator<T> creator = readParcelableCreator(loader);
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
}
return creator.createFromParcel(this);
}
As you can see the last call of that method is just calling the right Creator
but inside readParcelableCreator
there is a whole lot of reflexion that we can avoid by just calling it directly.
This utility calls may be useful:
import android.os.Parcel;
import android.os.Parcelable;
public class Parcels {
public static void writeBoolean(Parcel dest, Boolean value) {
dest.writeByte((byte) (value != null && value ? 1 : 0));
}
public static Boolean readBoolean(Parcel in){
return in.readByte() != 0;
}
public static void writeParcelable(Parcel dest, int flags, Parcelable parcelable) {
writeBoolean(dest, parcelable == null);
if (parcelable != null) {
parcelable.writeToParcel(dest, flags);
}
}
public static <T extends Parcelable> T readParcelable(Parcel in, Parcelable.Creator<T> creator) {
boolean isNull = readBoolean(in);
return isNull ? null : creator.createFromParcel(in);
}
}
The line:
obj = (A)in.readParcelable(A.class.getClassLoader());
should change to:
obj = (A)in.readParcelable(B.class.getClassLoader());
I encountered the same problem and did several Google search, many webpage or tutorial suggests we use A.class.getClassLoader()
because we are casting to A, but actually it is WRONG because you will get a null value, we must use B.class.getClassLoader()
because the codes are INSIDE class B
. I just did not know why but it can get the correct A object in this way.
Welcome to comment and verify!!
class B implements Parcelable{
//lets assume you have A as a data member
A obj;
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(obj , flags);
}
}
if you want to read it use this
obj = in.readParcelable(A.class.getClassLoader());