0

EDITED TO REFELECT qbix's answer

I have a class which holds data and is used for passing around data between activities. It has a couple of fields, mostly String, but 2 more fields which are of type ArrayList and another ArrayList

When I try to get the data from the intent back, I am getting an exception: java.lang.RuntimeException: Parcel android.os.Parcel@53614d6c: Unmarshalling unknown type code 7471184 at offset 156

I think that the problem lies somewhere with having an ArrayList which are not correctly handled.

How do I correctly implement Parcelable for ArrayList with custom types?

Here are my classes:

public class OpeningPeriod implements java.io.Serializable{
    private int openDay;
    private String openTime;
    private int closeDay;
    private String closeTime;

public OpeningPeriod() {
}

public OpeningPeriod(int closeDay, String closeTime, int openDay, String openTime) {
    this.closeDay = closeDay;
        this.closeTime = closeTime;
        this.openDay = openDay;
        this.openTime = openTime;
    }
    // here come the getters and setters....
}

And my edited Parcelable, which still crashes:

public class AddresseDetails implements Parcelable {
private String placeId;
private String strasse;
private String hausNummer;
private String ort;
private String plz;
private String phone;
private String web;
private ArrayList<String> weekDayText;
private String name;

public AddresseDetails() {
}

public AddresseDetails(Parcel source) {
    readFromParcel(source);
}

public AddresseDetails(String hausNummer,
                       String name,
                       String ort,
                       ArrayList<OpeningPeriod> periods,
                       String phone,
                       String placeId,
                       String plz,
                       String strasse,
                       String web,
                       ArrayList<String> weekDayText) {
    this.hausNummer = hausNummer;
    this.name = name;
    this.ort = ort;
    this.periods = periods;
    this.phone = phone;
    this.placeId = placeId;
    this.plz = plz;
    this.strasse = strasse;
    this.web = web;
    this.weekDayText = weekDayText;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeString(placeId);
    dest.writeString(strasse);
    dest.writeString(hausNummer);
    dest.writeString(ort);
    dest.writeString(plz);
    dest.writeString(phone);
    dest.writeString(web);

    dest.writeStringList(weekDayText);

}

public void readFromParcel(Parcel source){
    name = source.readString();
    placeId = source.readString();
    strasse = source.readString();
    hausNummer = source.readString();
    ort = source.readString();
    plz = source.readString();
    phone = source.readString();
    web = source.readString();

    source.readStringList(weekDayText);

}

public static final Parcelable.Creator<AddresseDetails> CREATOR = new Parcelable.Creator<AddresseDetails>() {

    @Override
    public AddresseDetails createFromParcel(Parcel source) {
        return new AddresseDetails(source);
    }

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

}

And it crashes in the source.readStringList(weekDayText);

Any suggestions?

Solution:

public class AddresseDetails implements Parcelable {
private String placeId;
private String strasse;
private String hausNummer;
private String ort;
private String plz;
private String phone;
private String web;
private ArrayList<String> weekDayText;
private ArrayList<OpeningPeriod> periods;
private String name;

public AddresseDetails() {
}

public AddresseDetails(Parcel source) {
    readFromParcel(source);
}

public AddresseDetails(String hausNummer,
                       String name,
                       String ort,
                       ArrayList<OpeningPeriod> periods,
                       String phone,
                       String placeId,
                       String plz,
                       String strasse,
                       String web,
                       ArrayList<String> weekDayText) {
    this.hausNummer = hausNummer;
    this.name = name;
    this.ort = ort;
    this.periods = periods;
    this.phone = phone;
    this.placeId = placeId;
    this.plz = plz;
    this.strasse = strasse;
    this.web = web;
    this.weekDayText = weekDayText;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeString(placeId);
    dest.writeString(strasse);
    dest.writeString(hausNummer);
    dest.writeString(ort);
    dest.writeString(plz);
    dest.writeString(phone);
    dest.writeString(web);

    dest.writeStringList(weekDayText);
    dest.writeTypedList(periods);

}

public void readFromParcel(Parcel source){
    name = source.readString();
    placeId = source.readString();
    strasse = source.readString();
    hausNummer = source.readString();
    ort = source.readString();
    plz = source.readString();
    phone = source.readString();
    web = source.readString();

    weekDayText = source.createStringArrayList();
    periods = source.createTypedArrayList(OpeningPeriod.CREATOR);

}

public static final Parcelable.Creator<AddresseDetails> CREATOR = new Parcelable.Creator<AddresseDetails>() {

    @Override
    public AddresseDetails createFromParcel(Parcel source) {
        return new AddresseDetails(source);
    }

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

    public static final Parcelable.Creator<OpeningPeriod> CREATOR = new Parcelable.Creator<OpeningPeriod>() {

    @Override
    public OpeningPeriod createFromParcel(Parcel source) {
        return new OpeningPeriod(source);
    }

    @Override
    public OpeningPeriod[] newArray(int size) {
        return new OpeningPeriod[size];
    }
};
}
mrd
  • 4,561
  • 10
  • 54
  • 92
  • Strange. I copied your code, made the correction in my answer and successfully stored and retrieved an AddresseDetails object in a Bundle. – Bob Snyder Jul 14 '15 at 15:51
  • @qbix how do you store and retrieve? – mrd Jul 14 '15 at 15:53
  • I posted my test code in my answer. After that, I also ran a test case where I added an AddresseDetails object to an intent and sent it to another Activity. Can't reproduce the exception you are seeing. – Bob Snyder Jul 14 '15 at 16:30
  • I found a solution based on your suggestions and Larry Schiefer's suggestion. I edited my question and added the answer. tx for your help – mrd Jul 14 '15 at 16:32

2 Answers2

0

Try using:

periods = source.readArrayList(OpeningPeriod.class.getClassLoader());
Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
0

Replace the constructor that takes Parcel parameter with this:

public AddresseDetails(Parcel source) {
    readFromParcel(source);
}

Your existing constructor is not reading the object members from the parcel in the same order they are written.

This is my test case. I'll experiment more. Maybe storing in a bundle doesn't invoke all the Parcel operations:

OpeningPeriod op = new OpeningPeriod(111, "close", 222, "open");
ArrayList<OpeningPeriod> periods = new ArrayList<>(3);
periods.add(op);

ArrayList<String> weekDays = new ArrayList<>(3);
weekDays.add("aaa");
weekDays.add("bbb");
weekDays.add("ccc");

AddresseDetails ad = new AddresseDetails("number", "name", "ort", periods, "phone",
        "place", "plz", "strasse", "web", weekDays);

Bundle b = new Bundle();
b.putParcelable("test", ad);

AddresseDetails ad2 = b.getParcelable("test");

Log.i("Test", "Phone=" + ad.phone + " " + ad2.phone);
Log.i("Test", "WeekDay1=" + ad.weekDayText.get(1) + " " + ad2.weekDayText.get(1));
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158