Это старый вопрос, но все не упоминают, что Enums на самом деле Serializable
и, следовательно, могут быть добавлены в Intent в качестве дополнительного. Как это:
public enum AwesomeEnum {
SOMETHING, OTHER;
}
intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING);
AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum");
Предложение использовать статические переменные или переменные всего приложения - действительно плохая идея. Это действительно связывает вашу деятельность с системой управления состоянием, и ее трудно поддерживать, отлаживать и решать проблемы.
АЛЬТЕРНАТИВЫ:
Тедзик отметил хороший момент в том, что решение, предоставленное Oderik, дает вам ошибку. Тем не менее, предлагаемая альтернатива немного громоздка в использовании (даже с использованием дженериков).
Если вы действительно беспокоитесь о возможности добавления enum к Intent, я предлагаю вместо этого следующие варианты:
ОПЦИЯ 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):
Это было давно, но с тех пор, как у нас появился Kotlin, я подумал, что добавлю еще одну опцию для новой парадигмы. Здесь мы можем использовать функции расширения и reified-типы (которые сохраняют тип при компиляции).
inline fun <reified T : Enum<T>> Intent.putExtra(victim: T): Intent =
putExtra(T::class.java.name, victim.ordinal)
inline fun <reified T: Enum<T>> Intent.getEnumExtra(): T? =
getIntExtra(T::class.java.name, -1)
.takeUnless { it == -1 }
?.let { T::class.java.enumConstants[it] }
Есть несколько преимуществ сделать это таким образом.
- Для выполнения сериализации нам не требуются «издержки» промежуточного объекта, поскольку все это делается на месте, благодаря
inline
чему вызовы заменяются кодом внутри функции.
- Функции более знакомы, так как они похожи на SDK.
- Среда IDE будет автоматически завершать эти функции, что означает, что нет необходимости предварительно знать класс утилит.
Одним из недостатков является то, что если мы изменим порядок Emums, то любая старая ссылка не будет работать. Это может быть проблемой с такими вещами, как Intents внутри ожидаемых намерений, поскольку они могут пережить обновления. Однако в остальное время все должно быть в порядке.
Важно отметить, что другие решения, такие как использование имени вместо позиции, также потерпят неудачу, если мы переименуем любое из значений. Хотя в этих случаях вместо неправильного значения Enum мы получаем исключение.
Использование:
// Sender usage
intent.putExtra(AwesomeEnum.SOMETHING)
// Receiver usage
val result = intent.getEnumExtra<AwesomeEnum>()