Search code examples
androidenumsparcelable

Parcelable object with enums in Android


In an android project i have a class with these fields:

public class TransactionHistoryDetail1 implements Parcelable, DatabaseEnabled{

    private long id;
    private static final String TABLE_NAME = "TransactionHistoryDetail";
    private static final String EMPTY_STRING = "";

    @XmlElement(name = "TxUd", required = true)
    private String TxUd;
    @XmlElement(name = "TxLclDtTm", required = true)
    private Date TxLclDtTm;
    @XmlElement(name = "CcyCd")
    private CurrencyCode CcyCd;
    @XmlElement(name = "Amt")
    private BigDecimal Amt;
    @XmlElement(name = "PmttpCd", required = true)
    private PaymentTypeCode PmttpCd;
    @XmlElement(name = "OprtnCd", required = true)
    private OperationCode OprtnCd;
    @XmlElement(name = "AppLabltpCd", required = true)
    private AppLabelTypeCode AppLabltpCd;
    @XmlElement(name = "PdSrl")
    private String PdSrl;
    @XmlElement(name = "PdBrndDsc")
    private String PdBrndDsc;
    @XmlElement(name = "UsrEml")
    private String UsrEml;
    @XmlElement(name = "CstmrAdr")
    private String CstmrAdr;
    @XmlElement(name = "TxDtlDsc")
    private String TxDtlDsc;
    @XmlElement(name = "TxRltdInd")
    private boolean TxRltdInd;
    @XmlElement(name = "TxSttsCd", required = true)
    private TransactionStatusCode TxSttsCd;
    @XmlElement(name = "UpdtDt", required = true)
    private Date UpdtDt;
...
}

Im trying to Write and Read objects of this class as Parcelables but im not sure how to write and read the enums.

My writeToParcel method looks like this:

   @Override
public void writeToParcel(Parcel dest, int flags) {

    SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);

    dest.writeLong(id);
    dest.writeDouble(Amt.doubleValue());
    dest.writeString(PdSrl);
    dest.writeString(PdBrndDsc);
    dest.writeString(TxUd);
    dest.writeString(PdSrl);
    dest.writeString(UsrEml);
    dest.writeString(CstmrAdr);
    dest.writeString(TxDtlDsc);
    dest.writeString((CcyCd == null) ? "" : CcyCd.name());
    dest.writeString((PmttpCd == null) ? "" : PmttpCd.name());
    dest.writeString((OprtnCd == null) ? "" : OprtnCd.name());
    dest.writeString((AppLabltpCd == null) ? "" : AppLabltpCd.name());
    dest.writeString(sdf.format(TxLclDtTm));
    dest.writeString(sdf.format(UpdtDt));
    dest.writeByte((byte) (TxRltdInd ? 1 : 0));
}

and my Constructor with Parcel looks like this

private TransactionHistoryDetail1(Parcel in) {

    SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);
    try {
        TxLclDtTm = sdf.parse(in.readString());
        UpdtDt = sdf.parse(in.readString());
    } catch (ParseException e) {
        e.printStackTrace();
    }
    id = in.readLong();
    TxUd = in.readString();
    PdSrl = in.readString();
    PdBrndDsc = in.readString();
    UsrEml = in.readString();
    CstmrAdr = in.readString();
    TxDtlDsc = in.readString();
    TxRltdInd = in.readByte() != 0;
    Amt = new BigDecimal(in.readDouble());
    CcyCd = CurrencyCode.valueOf(in.readString());
    PmttpCd = PaymentTypeCode.valueOf(in.readString());
    OprtnCd = OperationCode.valueOf(in.readString());
    AppLabltpCd = AppLabelTypeCode.valueOf(in.readString());
    TxSttsCd = TransactionStatusCode.fromValue(in.readString());

}

The writeToParcel i belive its working well, but the constructor is crashing at the "CcyCd" line.

My CurrencyCode class is a enum, (so are PaymentTypeCode,OperationCode and AppLabelTypeCode) that looks like this:

@XmlType(name = "CurrencyCode")
@XmlEnum
public enum CurrencyCode {

    EUR;

    public String value() {
        return name();
    }

    public static CurrencyCode fromValue(String v) {
        return valueOf(v);
    }
}

Is there another way to deal with enums in Parcelables?

The exception i get is this:

java.lang.RuntimeException: Unable to start activity ComponentInfo{package/package.activities.ChildActivity}: java.lang.IllegalArgumentException: No enum constant package.data.apiClasses.CurrencyCode.��EUR����CASH������CLS����APP����2017-04-10T09:07:52.525Z������2017-04-10T09:07:52.528Z�������� ��CHILD_12345������?


Solution

  • First of all you should read from the Parcel in the exact order that you wrote to it. Since Parcel just write and read data in order instead of actually serializing data you have to keep read and write in order else you gonna read wrong values and getting error..

    It is the best if you treat Enum as int, write them to parcel like this:

    dest.writeInt(this.CcyCd == null ? -1 : this.CurrencyCode.ordinal());
    

    and read them like this:

    int tmpCurrencyCode = in.readInt();
    this.CcyCd = tmpCurrencyCode == -1 ? null : CurrencyCode.values()[tmpMState];
    

    P.S: This code check for null values too ^^