postman icon indicating copy to clipboard operation
postman copied to clipboard

Parceling Parent Class Fields

Open KennethNickles opened this issue 9 years ago • 2 comments

I have two classes:

@Parceled
public class A implements Parcelable {

    public static final Creator<A> CREATOR = Postman.getCreator(A.class);

    State mState;

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        Postman.writeToParcel(this, dest);
    }

    @Parceled
    public static class State implements Parcelable {

        public static final Creator<State> CREATOR = Postman.getCreator(State.class);

        // Postman Fields

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            Postman.writeToParcel(this, dest);
        }
    }
}

and

@Parceled
public class B extends A implements Parcelable {

    public static final Creator<B> CREATOR = Postman.getCreator(B.class);

    State mState

@Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        Postman.writeToParcel(this, dest);
    }

    @Parceled
    public static class State extends A.State implements Parcelable {

        public static final Creator<State> CREATOR = Postman.getCreator(State.class);

        // Postman Fields

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            Postman.writeToParcel(this, dest);
        }
    }
}

As far as I can tell the State$$Parceler only handles its own fields, but the B$$Parceler seems to be setting the State field twice. Once I assume is for the A.State field and the other for the B.State field.

public final class B$State$$Parceler implements Parceler<B.State> {

  @Override
  public void writeToParcel(B.State object, Parcel dest) {
    Bundle bundle = new Bundle();
    bundle.putInt("mSomeCustomField", object.mSomeCustomField);
    dest.writeBundle(bundle);
  }

  @Override
  public B.State readFromParcel(Parcel parcel) {
    B.State object = new B.State();
    Bundle bundle = parcel.readBundle();
    bundle.setClassLoader(B.State.class.getClassLoader());
    object.mCurrentManaCost = bundle.getInt("mCurrentManaCost");
    return object;
  }

  @Override
  public B.State[] newArray(int size) {
    return new B.State[size];
  }

}

public final class B$$Parceler implements Parceler<B> {

  @Override
  public void writeToParcel(B object, Parcel dest) {
    Bundle bundle = new Bundle();
    bundle.putParcelable("mState", object.mState);
    bundle.putParcelable("mState", object.mState);
    dest.writeBundle(bundle);
  }

  @Override
  public Commander readFromParcel(Parcel parcel) {
    B object = new B();
    Bundle bundle = parcel.readBundle();
    bundle.setClassLoader(B.class.getClassLoader());
    object.mState = bundle.getParcelable("mState");
    object.mState = bundle.getParcelable("mState");
    return object;
  }

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

}

Can you explain how these parcelers handle class hierarchy and if this is a problem?

KennethNickles avatar May 01 '16 07:05 KennethNickles

Well, it doesn't seem like it would cause any issues, but no, it was not the intention to do the assignment twice. I'll take a look at it tomorrow.

ndtaylor avatar May 04 '16 14:05 ndtaylor

This can actually cause some interesting problems that will cause Postman to not compile. The way I'd like to solve this is to have separate Parcelers for super classes which the subclasses delegate to. There is probably a smaller change I can make that will fix the issue, but if no one is negatively affected by this bug right now, I'll skip the quick fix.

ndtaylor avatar Jun 13 '16 01:06 ndtaylor