To stare pytanie, ale wszyscy nie wspominają, że Enumy są w rzeczywistości Serializablei dlatego można je idealnie dodać do Intencji jako dodatek. Lubię to:
public enum AwesomeEnum {
SOMETHING, OTHER;
}
intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING);
AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum");
Sugestia użycia zmiennych statycznych lub obejmujących całą aplikację jest naprawdę złym pomysłem. To naprawdę łączy twoje działania z systemem zarządzania stanem i jest trudne do utrzymania, debugowania i problemów.
ALTERNATYWY:
Tedzyc zauważył , że rozwiązanie dostarczone przez Oderik daje błąd. Jednak oferowana alternatywa jest nieco kłopotliwa w użyciu (nawet przy użyciu generycznych).
Jeśli naprawdę martwisz się wydajnością dodawania wyliczenia do zamiaru, proponuję zamiast tego następujące alternatywy:
OPCJA 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)];
}
}
Stosowanie:
// Sender usage
AwesomeEnum.SOMETHING.attachTo(intent);
// Receiver usage
AwesomeEnum result = AwesomeEnum.detachFrom(intent);
OPCJA 2:
(ogólna, wielokrotnego użytku i oddzielona od wyliczenia)
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);
}
}
Stosowanie:
// Sender usage
EnumUtil.serialize(AwesomeEnum.Something).to(intent);
// Receiver usage
AwesomeEnum result =
EnumUtil.deserialize(AwesomeEnum.class).from(intent);
OPCJA 3 (z Kotlin):
Minęło trochę czasu, ale odkąd mamy Kotlina, pomyślałem, że dodam kolejną opcję dla nowego paradygmatu. Tutaj możemy skorzystać z funkcji rozszerzeń i typów zmienionych (które zachowują typ podczas kompilacji).
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] }
Jest kilka korzyści z robienia tego w ten sposób.
- Nie wymagamy „narzutu” obiektu pośredniego, aby wykonać serializację, ponieważ wszystko odbywa się w miejscu, dzięki
inlineczemu zastąpi wywołania kodem wewnątrz funkcji.
- Funkcje są bardziej znane, ponieważ są podobne do tych z zestawu SDK.
- IDE automatycznie uzupełni te funkcje, co oznacza, że nie ma potrzeby wcześniejszej znajomości klasy użytkowej.
Jedną z wad jest to, że jeśli zmienimy kolejność Emums, żadne stare odniesienie nie będzie działać. Może to być problem z rzeczami takimi jak intencje w toku, ponieważ mogą przetrwać aktualizacje. Jednak przez resztę czasu powinno być w porządku.
Ważne jest, aby pamiętać, że inne rozwiązania, takie jak użycie nazwy zamiast pozycji, również zawiodą, jeśli zmienimy nazwę dowolnej z wartości. Chociaż w takich przypadkach otrzymujemy wyjątek zamiast niepoprawnej wartości Enum.
Stosowanie:
// Sender usage
intent.putExtra(AwesomeEnum.SOMETHING)
// Receiver usage
val result = intent.getEnumExtra<AwesomeEnum>()