Как читать и писать Enum в посылку на Android?

Вот мой модельный класс:

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

10 ответов

У меня была похожая проблема, и мое решение было:

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

и для чтения:

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

QuestionType перечислите и помните, что порядок элементов имеет значение.

Самый эффективный - эффективный для памяти - пакет создается с использованием порядкового значения ENUM.

Письмо посылке dest.writeInt(enum_variable.ordinal());

Чтение из посылки enum_variable = EnumName.values()[in.readInt()];

Это должно быть хорошо, если вы не прислушаетесь к указаниям документации:

Посылка не является универсальным механизмом сериализации. Этот класс (и соответствующий API Parcelable для размещения произвольных объектов в Parcel) разработан как высокопроизводительный транспорт IPC. Таким образом, нецелесообразно помещать какие-либо данные об участках в постоянное хранилище: изменения в базовой реализации любых данных в участке могут сделать более старые данные нечитаемыми.

Другими словами, вы не должны передавать Parcels между версиями кода, потому что это может не сработать.

Любой enum Сериализуем.

Вы можете сделать это в writeToParcel(): dest.writeSerializable(action)

И в конструкторе: action = (Action) in.readSerializable()

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

Теперь вы можете написать что-то подобное с помощью Kotlin Parcelize:

      import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
class NetworkError(
    var imageId: Int,
    var description: String,
    var actionName: String,
    private val action: Action
): Parcelable {

    @Parcelize
    enum class Action: Parcelable {
        RETRY, SETTINGS
    }
}

Пример Kotlin-кода (нулевой безопасный):

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 }

Один из способов сделать это - записать действия в целое число, правильно прочитать их как целое и преобразовать их в действие. Что я имею в виду:

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

Попытайся. Успех...

Прочитать посылку

      action = Nav.valueOf(in.readString());

Написать посылку

      out.writeString(action.name());

Вы пробовали так

      @Parcelize enum class State {
    ON, OFF
}

@Parcelize
class PowerSwitch(var state: State) : Parcelable

Дайте мне знать, это работает для вас или нет?

Используя тот факт, что перечисления сериализуемы

Мое перечисление:

      public enum HouseEnum {
    GRYFFINDOR, HUFFLEPUFF, RAVENCLAW, SLYTHERIN
}

При размещении в пачке:

      args.putSerializable(HOUSE, houseEnum);

При извлечении из пакета:

      houseEnum = (HouseEnum) getArguments().getSerializable(HOUSE);
Другие вопросы по тегам