AppDeveloper
AppDeveloper

Reputation: 2210

write parcelable on enum is crashing the app

This line is dest.writeParcelable(department, flags); causing the app to crash as I parcel the object via the intent.

When I comment the line, the app goes through but of course I don't have the department value.

public class User implements Parcelable {

    public String id;
    public String name;
    public String email;
    public Department department;

    // other implementations of Parcelable 

protected UserVO(Parcel in) {
    id = in.readString();
    name = in.readString();
    email = in.readString();
    department = in.readParcelable(Department.class.getClassLoader());
}


    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
        dest.writeString(email);
        dest.writeParcelable(department, flags); // crashes
    }
}

Department Enum

public enum Department implements Parcelable {

    SALES("Sales", 1),
    HR("Human Resources", 2),
    SHIPPING("Shipping", 3),

    public final String name;
    public final int ordinal;

    Department(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

    Department(Parcel in) {
        name = in.readString();
        ordinal = in.readInt();
    }

    public static final Creator<Department> CREATOR = new Creator<Department>() {
        @Override
        public Department createFromParcel(Parcel in) {
            return Department.valueOf(in.readString()); // crash
            //return new DeptEnum(in); // android studio generated code but has error: enum types may not be instantiated
        }

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

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(ordinal);
    }
}

Error

No enum constant Department.Sales

I took the help from this answer for the line return Department.valueOf(in.readString());


Observation

I guess it has to do something with having both name and ordinal values, my enum type is not simple as in the linked answer, somehow I need to create an enum from parcel.

public Department createFromParcel(Parcel in) {
    Log.d("abc", "createFromParcel: " + in.readString()); // returns null
    Log.d("abc", "createFromParcel: " + in.readInt()); // returns 127 or 128
    return SHIPPING; // hard coded value works but of course not a solution
}

Upvotes: 0

Views: 801

Answers (1)

OneCricketeer
OneCricketeer

Reputation: 191725

You don't need to parcel the ordinal. Doing valueOf alone on the name would be fine

However, the parameter of valueOf must match exactly the enum defined name.

For example, this would work for sales and shipping, but not HR

Department.valueOf(in.readString().toUpperCase());

The solution you need is to loop over Department.values() and compare each name field of the values with the in.readString() result

How can I lookup a Java enum from its String value?

Or you could use the ordinal instead like so, although you're duplicating ordinal information and you'd have to guarantee that the enums have sequential numbers

 return Department.values()[in.readInt() - 1]

Upvotes: 1

Related Questions