Как читать и писать 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);