Это старый вопрос, но все не упоминают, что Enums на самом деле Serializable
и поэтому могут быть идеально добавлены в Intent в качестве дополнительного. Как это:
public enum AwesomeEnum {
SOMETHING, OTHER;
}
intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING);
AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum");
Предложение использовать статические или прикладные переменные - действительно плохая идея. Это действительно связывает вашу деятельность с системой управления состоянием, и ее трудно поддерживать, отлаживать и решать проблемы.
АЛЬТЕРНАТИВЫ:
tedzyc отметил, что решение, предоставленное Oderik , дает вам ошибку. Тем не менее, предоставленная альтернатива немного рушится - некоторые используют (даже используя дженерики).
Если вы действительно беспокоитесь о возможности добавления enum к намерению, я предлагаю вместо этого следующие варианты:
ВАРИАНТ 1:
public enum AwesomeEnum {
SOMETHING, OTHER;
private static final String name = AwesomeEnum.class.getName();
public void attachTo(Intent intent) {
intent.putExtra(name, ordinal());
}
public static AwesomeEnum detachFrom(Intent intent) {
if(!intent.hasExtra(name)) throw new IllegalStateException();
return values()[intent.getIntExtra(name, -1)];
}
}
Использование:
// Sender usage
AwesomeEnum.SOMETHING.attachTo(intent);
// Receiver usage
AwesomeEnum result = AwesomeEnum.detachFrom(intent);
ВАРИАНТ 2:
(универсальный, многократно используемый и отделенный от перечисления)
public final class EnumUtil {
public static class Serializer<T extends Enum<T>> extends Deserializer<T> {
private T victim;
@SuppressWarnings("unchecked")
public Serializer(T victim) {
super((Class<T>) victim.getClass());
this.victim = victim;
}
public void to(Intent intent) {
intent.putExtra(name, victim.ordinal());
}
}
public static class Deserializer<T extends Enum<T>> {
protected Class<T> victimType;
protected String name;
public Deserializer(Class<T> victimType) {
this.victimType = victimType;
this.name = victimType.getName();
}
public T from(Intent intent) {
if (!intent.hasExtra(name)) throw new IllegalStateException();
return victimType.getEnumConstants()[intent.getIntExtra(name, -1)];
}
}
public static <T extends Enum<T>> Deserializer<T> deserialize(Class<T> victim) {
return new Deserializer<T>(victim);
}
public static <T extends Enum<T>> Serializer<T> serialize(T victim) {
return new Serializer<T>(victim);
}
}
Использование:
// Sender usage
EnumUtil.serialize(AwesomeEnum.Something).to(intent);
// Receiver usage
AwesomeEnum result =
EnumUtil.deserialize(AwesomeEnum.class).from(intent);
ВАРИАНТ 3 (с Kotlin):
Прошло много времени, но, поскольку теперь у нас есть Котлин, я подумал, что добавлю еще одну опцию для новой парадигмы. Здесь мы можем использовать функции расширения и расширенные типы (которые сохраняют тип при компиляции).
inline fun <reified T : Enum<T>> Intent.putExtra(victim: T): Intent =
putExtra(T::class.qualifiedName, victim.ordinal)
inline fun <reified T: Enum<T>> Intent.getEnumExtra(): T? =
getIntExtra(T::class.qualifiedName, -1)
.takeUnless { it == -1 }
?.let { T::class.java.enumConstants[it] }
Есть несколько преимуществ сделать это таким образом.
- Для выполнения сериализации нам не нужны «издержки» промежуточного объекта, поскольку все это выполняется на месте благодаря
inline
, который заменит вызовы кодом внутри функции.
- Функции более знакомы, так как они похожи на функции SDK.
- Среда IDE будет автоматически завершать эти функции, что означает, что нет необходимости предварительно знать класс утилит.
Использование:
// Sender usage
intent.putExtra(AwesomeEnum.SOMETHING)
// Receiver usage
val result = intent.getEnumExtra<AwesomeEnum>()