0

I haven't understood how to create the code needed to implement correctly the Parcelable for an object that contains GregorianCalendar objects.

E.g. for an object User that contains String name; and GregorianCalendar creationDate;, my attempt is this:

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

@Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeParcelable(this.creationDate, flags);
    }

    private User(Parcel in) {
        this.name = in.readString();
        this.creationDate = in.readParcelable(GregorianCalendar.class.getClassLoader());
    }

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

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

that unfortunately doesn't work

in writeToParcel() at the line

dest.writeParcelable(this.creationDate, flags);

get writeParcelable cannot be applied to GregorianCalendar error

in

this.creationDate = in.readParcelable(GregorianCalendar.class.getClassLoader());

get Incompatible types error

How to code correctly the Parcelable?

EDIT

I have tried some code generators but use different ways and I'm not sure what is the right implementation, the first one use writeValue and readValue in this way:

 @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeValue(creationDate);
    }

 protected User(Parcel in) {
        name = in.readString();
        creationDate = (GregorianCalendar) in.readValue(GregorianCalendar.class.getClassLoader());
    }

the second one use

 @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
            dest.writeSerializable(creationDate);
        }

     protected User(Parcel in) {
            name = in.readString();
            creationDate = (GregorianCalendar) in.readSerializable();
        }

What is the right way?

AndreaF
  • 11,975
  • 27
  • 102
  • 168
  • have you tried using http://www.parcelabler.com/ ? – EpicPandaForce Oct 11 '14 at 14:49
  • No but I have tried to use a parcelable code generator plugin but creates wrong code. The site that you have linked use `creationDate = (GregorianCalendar) in.readValue(GregorianCalendar.class.getClassLoader());` and `dest.writeValue(creationDate);` could you confirm that is the right way to Parcel GregorianCalendar? – AndreaF Oct 11 '14 at 14:55
  • 2
    see Calendar.getTimeInMillis/Calendar.setTimeInMillis – pskink Oct 11 '14 at 15:11
  • @pskink what do you mean? – AndreaF Oct 11 '14 at 15:18
  • just parcel the long millis value – pskink Oct 11 '14 at 15:59
  • To use millis I have to change too much codelines. I prefer to use a valid way to parcel GregorianCalendar. Anyway I haven't understood the reason why using millisecond should be a better way according to you. – AndreaF Oct 11 '14 at 16:20
  • he is right, if you can't send the object over then just get the date out in milis (long) and send that over in the parcel. – EpicPandaForce Oct 11 '14 at 19:00
  • I have no doubt that also the millisecond could be used in some way, but I want to Parcel `GregorianCalendar` to avoid to change others already coded methods. Someone could tell me what is the righ way to Parcel `GregorianCalendar`? What about the 2 different methods in the EDIT? Are valid? If yes what shoud I use? – AndreaF Oct 11 '14 at 19:55
  • who has downvoted the question? what is the reason? – AndreaF Oct 12 '14 at 14:28

1 Answers1

2

You could use the second way since GregorianCalendar implements Serializable, and the Parcelable will work.

      @Override
      public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
            dest.writeSerializable(creationDate);
      }

     protected User(Parcel in) {
            name = in.readString();
            creationDate = (GregorianCalendar) in.readSerializable();
     }

However you MUST NOT serialize GregorianCalendar, because updates in GregorianCalendar related class can cause issue. Consider the case you load a file that contains GregorianCalendar objects created with a different API version, the difference in GregorianCalendar implementation will lead to sure errors, is enough a little difference in serialVersionUID costant to prevent the correct load of the file.

Use long parameters to store the millisecond of the date, if you don't want to rewrite your whole application you can easily create a couple of methods to convert from millis to GregorianCalendar and vice-versa as you need.

Silverstorm
  • 15,398
  • 2
  • 38
  • 52