Kiedyś definiowałem zestaw powiązanych stałych, takich jak Bundle
klucze razem w interfejsie jak poniżej:
public interface From{
String LOGIN_SCREEN = "LoginSCreen";
String NOTIFICATION = "Notification";
String WIDGET = "widget";
}
Zapewnia mi to przyjemniejszy sposób grupowania powiązanych stałych razem i używania ich przez import statyczny (nie implementuje). Wiem Android
ramy stosowane są także stałe w taki sam sposób jak Toast.LENTH_LONG
, View.GONE
.
Jednak często czuję, że Java Enums
zapewniają znacznie lepszy i potężniejszy sposób przedstawiania stałej.
Ale czy istnieje problem wydajno w użyciu enums
na Android
?
Po krótkich badaniach znalazłem się w zamieszaniu. Z tego pytania
„Unikaj wyliczeń tam, gdzie potrzebujesz tylko Ints” zostało usunięte ze wskazówek dotyczących wydajności Androida? Jasne jest, że Google
usunięto „Unikaj wyliczeń” ze wskazówek dotyczących wydajności, ale z oficjalnych dokumentów szkoleniowych Należy pamiętać o sekcji poświęconej pamięci, która wyraźnie mówi: „Wyliczenia często wymagają więcej niż dwa razy więcej pamięci niż stałe statyczne. Należy bezwzględnie unikać wyliczeń w systemie Android. „ Czy to nadal jest dobre? (Powiedzmy w Java
wersjach po 1.6)
Jeszcze jedna kwestia, że obserwowana jest przesłanie enums
całej intents
użyciu Bundle
powinienem wysłać je przez szeregowania (czyli putSerializable()
, że myślę, że operacja kosztowna w porównaniu do pierwotnej putString()
metodzie, mimo iż enums
stanowi to za darmo).
Czy ktoś może wyjaśnić, który z nich jest najlepszy do reprezentowania tego samego w Android
? Czy powinienem unikać używania enums
na Android
?
Enum.ordinal()
zamiast tego przekazać go jako int używając .Odpowiedzi:
Używaj,
enum
gdy potrzebujesz jego funkcji. Nie unikaj tego ściśle .Wyliczenie w Javie jest potężniejsze, ale jeśli nie potrzebujesz jego funkcji, użyj stałych, zajmują one mniej miejsca i same mogą być prymitywne.
Kiedy używać wyliczenia:
przeciążanie metody - każda stała wyliczeniowa ma swoją własną implementację metody
public enum UnitConverter{ METERS{ @Override public double toMiles(final double meters){ return meters * 0.00062137D; } @Override public double toMeters(final double meters){ return meters; } }, MILES{ @Override public double toMiles(final double miles){ return miles; } @Override public double toMeters(final double miles){ return miles / 0.00062137D; } }; public abstract double toMiles(double unit); public abstract double toMeters(double unit); }
więcej danych - Twoja jedna stała zawiera więcej niż jedną informację, której nie można umieścić w jednej zmiennej
Kiedy nie używać wyliczenia:
możesz akceptować ciągłe dane
public class Month{ public static final int JANUARY = 1; public static final int FEBRUARY = 2; public static final int MARCH = 3; ... public static String getName(final int month){ if(month <= 0 || month > 12){ throw new IllegalArgumentException("Invalid month number: " + month); } ... } }
Enum zajmuje więcej miejsca
Stałe zajmują mniej miejsca
źródło
Jeśli wyliczenia mają po prostu wartości, powinieneś spróbować użyć IntDef / StringDef, jak pokazano tutaj:
https://developer.android.com/studio/write/annotations.html#enum-annotations
Przykład: zamiast:
enum NavigationMode {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}
używasz:
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) @Retention(RetentionPolicy.SOURCE) public @interface NavigationMode {} public static final int NAVIGATION_MODE_STANDARD = 0; public static final int NAVIGATION_MODE_LIST = 1; public static final int NAVIGATION_MODE_TABS = 2;
aw funkcji, która ma to jako parametr / zwróconą wartość, użyj:
@NavigationMode public abstract int getNavigationMode(); public abstract void setNavigationMode(@NavigationMode int mode);
W przypadku, gdy wyliczenie jest złożone, użyj wyliczenia. Nie jest tak źle.
Aby porównać wyliczenia ze stałymi wartościami, należy przeczytać tutaj:
Ich przykładem jest wyliczenie z 2 wartościami. Zajmuje 1112 bajtów w pliku dex w porównaniu do 128 bajtów, gdy używane są stałe liczby całkowite. Ma to sens, ponieważ wyliczenia są prawdziwymi klasami, w przeciwieństwie do tego, jak to działa w C / C ++.
źródło
IntDef
adnotacją, tak się stanie. Co do zegarków, myślę, że też jest całkiem jasne. Które urządzenie ma więcej mocy procesora, pamięci RAM i baterii: telefon czy zegarek? A które z nich wymagają oprogramowania, aby było bardziej zoptymalizowane pod kątem wydajności z tego powodu?Oprócz wcześniejszych odpowiedzi dodam, że jeśli korzystasz z Proguard (i zdecydowanie powinieneś to zrobić, aby zmniejszyć rozmiar i zaciemnić swój kod), to Twój
Enums
zostanie automatycznie przekonwertowany na@IntDef
tam, gdzie jest to możliwe:https://www.guardsquare.com/en/proguard/manual/optimizations
Dlatego jeśli masz jakieś dyskretne wartości i jakaś metoda powinna pozwolić na pobranie tylko tych wartości, a nie innych tego samego typu, to użyłbym
Enum
, ponieważ Proguard wykona tę ręczną pracę optymalizacji kodu za mnie.I oto dobry post o używaniu wyliczeń Jake'a Whartona, spójrz na to.
źródło
Nie. „ Ściśle ” oznacza, że są tak złe, że w ogóle nie powinny być używane. Możliwe, że w ekstremalnej sytuacji mogą wystąpić problemy z wydajnością, takie jak wiele wielu (tysięcy lub milionów) operacji z wyliczeniami (kolejno w wątku interfejsu użytkownika). O wiele bardziej powszechne są sieciowe operacje we / wy, które powinny być wykonywane wyłącznie w wątku w tle. Najczęstszym wykorzystanie teksty stałe jest prawdopodobnie jakiś rodzaj czeku typu - czy przedmiot jest to albo że który jest tak szybka, że nie będzie w stanie dostrzec różnicę między jednym porównania teksty stałe i porównywania liczb.
Nie ma na to ogólnej zasady. Użyj tego, co działa dla Ciebie i pomoże Ci przygotować aplikację. Optymalizuj później - gdy zauważysz, że występuje wąskie gardło, które spowalnia niektóre aspekty aplikacji.
źródło
W przypadku Androida P Google nie ma żadnych ograniczeń / sprzeciwów w używaniu wyliczeń
Dokumentacja zmieniła się tam, gdzie wcześniej zalecano ostrożność, ale teraz nie wspomina o tym. https://developer.android.com/reference/java/lang/Enum
źródło
Dwa fakty.
1, Enum jest jedną z najpotężniejszych funkcji JAVA.
2, telefon z Androidem ma zwykle dużo pamięci.
Więc moja odpowiedź brzmi NIE. Będę używać Enum w systemie Android.
źródło
Chciałbym dodać, że nie możesz używać @Annotations, gdy deklarujesz List <> lub Map <>, gdzie klucz lub wartość jest jednym z twoich interfejsów adnotacji. Pojawia się błąd „Adnotacje są tu niedozwolone”.
enum Values { One, Two, Three } Map<String, Values> myMap; // This works // ... but ... public static final int ONE = 1; public static final int TWO = 2; public static final int THREE = 3; @Retention(RetentionPolicy.SOURCE) @IntDef({ONE, TWO, THREE}) public @interface Values {} Map<String, @Values Integer> myMap; // *** ERROR ***
Więc kiedy musisz spakować go do listy / mapy, użyj enum, ponieważ można je dodać, ale @annotated int / string group nie może.
źródło