如何在Android上读取和写入Enum到parcel?

时间:2016-07-03 22:44:03

标签: android enums parcelable parcel

这是我的模特课:

public enum Action {
    RETRY, SETTINGS
}

private int imageId;
private String description;
private String actionName;
private Action action;

public NetworkError(int imageId, String description, String actionName, Action action ) {
    this.imageId = imageId;
    this.description = description;
    this.actionName = actionName;
    this.action = action;
}

public int getImageId() {
    return imageId;
}

public void setImageId(int imageId) {
    this.imageId = imageId;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public String getActionName() {
    return actionName;
}

public void setActionName(String actionName) {
    this.actionName = actionName;
}


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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(this.imageId);
    dest.writeString(this.description);
    dest.writeString(this.actionName);
}

protected NetworkError(Parcel in) {
    this.imageId = in.readInt();
    this.description = in.readString();
    this.actionName = in.readString();
}

public static final Parcelable.Creator<NetworkError> CREATOR = new Parcelable.Creator<NetworkError>() {
    @Override
    public NetworkError createFromParcel(Parcel source) {
        return new NetworkError(source);
    }

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

6 个答案:

答案 0 :(得分:48)

我有类似的问题,我的解决方案是:

parcel.writeString(this.questionType.name());

并阅读:

this.questionType = QuestionType.valueOf(parcel.readString());

QuestionType是枚举,请记住元素的排序很重要。

答案 1 :(得分:21)

最高效 - 内存高效 - 使用ENUM序数值创建捆绑包。

写入包裹dest.writeInt(enum_variable.ordinal());

从地块enum_variable = EnumName.values()[in.readInt()];

中读取

除非你不注意文档的警告,否则这应该没问题:

  

Parcel不是通用序列化机制。此类(以及用于将任意对象放入包中的相应Parcelable API)被设计为高性能IPC传输。因此,将任何Parcel数据放入持久存储中是不合适的:Parcel中任何数据的底层实现的更改都可能导致旧数据不可读。

换句话说,您不应该在代码版本之间传递Parcel,因为它可能无效。

答案 2 :(得分:20)

任何enum都是可序列化的。

您可以在writeToParcel()dest.writeSerializable(action)

中执行此操作

在构造函数中:action = (Action) in.readSerializable()

答案 3 :(得分:2)

Enum decleration:

public enum Action {

    NEXT(1),
    OK(2);

    private int action;

    Action(int action) {
        this.action = action;
    }

}

从包裹中读取:

protected ActionParcel(Parcel in) {
    int actionTmp = in.readInt();
    action = Tutorials.Action.values()[actionTmp];
}

写入包裹:

public void writeToParcel(Parcel dest, int flags) {
    int actionTmp = action == null ? -1 : action.ordinal();
    dest.writeInt(actionTmp);
}

答案 4 :(得分:1)

执行此操作的一种方法是以整数形式编写动作,并将其正确地读取为整数,然后将其转换为动作。我的意思是:

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(this.imageId);
    dest.writeString(this.description);
    dest.writeString(this.actionName);

    int actionAsInt = action == Action.RETRY ? 1 : 0;
    dest.writeInt(actionAsInt);
}

protected NetworkError(Parcel in) {
    this.imageId = in.readInt();
    this.description = in.readString();
    this.actionName = in.readString();

    int actionAsInt = in.readInt();
    this.action = actionAsInt == 1 ? Action.RETRY : Action.SETTINGS;
}

尝试一下。成功...

答案 5 :(得分:0)

科特林代码示例(null-safe):

writeInt(action?.ordinal ?: -1)

action = readInt().let { if (it >= 0) enumValues<MyEnum>()[it] else null }

哪些可以封装在write / readEnum方法中作为Parcel的扩展:

fun <T : Enum<T>> Parcel.writeEnum(value: T?) = 
    writeInt(value?.ordinal ?: -1)

inline fun <reified T : Enum<T>> Parcel.readEnum(): T? = 
    readInt().let { if (it >= 0) enumValues<T>()[it] else null }