【问题标题】:Android: How do I correctly implement Parcelable for Objects with ArrayList<T> with custom types?Android:如何使用自定义类型为具有 ArrayList<T> 的对象正确实现 Parcelable?
【发布时间】:2015-07-14 11:37:00
【问题描述】:

编辑以反映 qbix 的答案

我有一个保存数据的类,用于在活动之间传递数据。它有几个字段,主要是字符串,但还有 2 个字段类型为 ArrayList 和另一个 ArrayList

当我尝试从意图中获取数据时,我遇到了一个异常: java.lang.RuntimeException: Parcel android.os.Parcel@53614d6c: Unmarshalling unknown type code 7471184 at offset 156

我认为问题在于没有正确处理的 ArrayList。

如何使用自定义类型正确实现 Parcelable for ArrayList?

这是我的课程:

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....
}

我编辑的 Parcelable 仍然崩溃:

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];
    }
};

}

它在source.readStringList(weekDayText); 中崩溃

有什么建议吗?

解决方案:

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];
    }
};
}

【问题讨论】:

  • 奇怪。我复制了您的代码,在我的答案中进行了更正,并成功地在 Bundle 中存储和检索了 AddresseDetails 对象。
  • @qbix 如何存储和检索?
  • 我在答案中发布了我的测试代码。之后,我还运行了一个测试用例,其中我将一个 AddresseDetails 对象添加到一个意图并将其发送到另一个 Activity。无法重现您看到的异常。
  • 我根据您的建议和 Larry Schiefer 的建议找到了解决方案。我编辑了我的问题并添加了答案。 tx 为您提供帮助

标签: android arraylist parcelable


【解决方案1】:

将带有 Parcel 参数的构造函数替换为:

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

您现有的构造函数没有按照写入顺序从包中读取对象成员。

这是我的测试用例。我会做更多的实验。也许存储在一个包中不会调用所有 Parcel 操作:

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));

【讨论】:

    【解决方案2】:

    尝试使用:

    periods = source.readArrayList(OpeningPeriod.class.getClassLoader());
    

    【讨论】:

      猜你喜欢
      • 2021-12-02
      • 2011-10-25
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多