Dlaczego Android nie używa więcej wyliczeń?

79

Zacząłem bardzo lubić używanie wyliczeń C # i Java w moim kodzie z kilku powodów:

  • Są znacznie bardziej bezpieczne dla typów niż liczby całkowite, łańcuchy lub zestawy flag logicznych.
  • Prowadzą do bardziej czytelnego kodu.
  • Trudniej jest ustawić wyliczenie na nieprawidłową wartość niż wartość typu int lub string.
  • Ułatwiają odkrywanie dozwolonych wartości zmiennej lub parametru.
  • Wszystko, co przeczytałem, wskazuje, że działają one równie dobrze jak liczby całkowite w C # i większości maszyn JVM.

Jednak struktura systemu Android ma wiele przypadków, w których flagi różnych typów muszą być przekazywane, ale żaden z nich nie wydaje się używać wyliczeń. Kilka przykładów gdzie myślę, że ich stosowanie byłoby korzystne są Toast.LENGTH_SHORT/ Toast.LENGTH_LONGa View.GONE, View.VISIBLEitp

Dlaczego to? Czy wyliczenia działają gorzej niż proste wartości całkowite w Dalvik? Czy jest jakaś inna wada, której nie jestem świadomy?

Wszyscy jesteśmy Monica
źródło
10
Teraz możesz użyć enum. Zobacz stackoverflow.com/questions/5143256/…
Thierry-Dimitri Roy
1
Świetny! Lubię enumy i jeszcze nie zabrałem się za ich wyjęcie.
Wszyscy jesteśmy Monica

Odpowiedzi:

66

Ta odpowiedź jest nieaktualna w marcu 2011 r.

Wyliczenia mogą być używane we Froyo i nowszych wersjach - zgodnie z tą odpowiedzią ( dlaczego „Unikaj wyliczeń tam, gdzie potrzebujesz tylko Ints” usunięto ze wskazówek dotyczących wydajności Androida? ) Od członka zespołu Android VM (i jego bloga ).


Poprzednia odpowiedź:

Oficjalnym zaleceniem zespołu ds. Androida jest unikanie wyliczeń, ilekroć możesz tego uniknąć:

Wyliczenia są bardzo wygodne, ale niestety mogą być bolesne, gdy liczą się rozmiar i szybkość. Na przykład to:

public enum Shrubbery { GROUND, CRAWLING, HANGING }

dodaje 740 bajtów do pliku .dex w porównaniu z równoważną klasą z trzema publicznymi statycznymi końcowymi wartościami int. Przy pierwszym użyciu inicjator klasy wywołuje metodę na obiektach reprezentujących każdą z wyliczonych wartości. Każdy obiekt otrzymuje własne pole statyczne, a pełny zestaw jest przechowywany w tablicy (statycznym polu o nazwie „$ VALUES”). To dużo kodu i danych, tylko dla trzech liczb całkowitych. Dodatkowo to:

Shrubbery shrub = Shrubbery.GROUND;

powoduje statyczne wyszukiwanie pól. Gdyby „GROUND” było statyczną wartością końcową int, kompilator potraktowałby ją jako znaną stałą i wstawiłaby do niej.

Źródło: Unikaj wyliczeń tam, gdzie potrzebujesz tylko Ints

Sebastian Paaske Tørholm
źródło
4
Więc podczas gdy C # teksty stałe należy wykonać bardzo dobrze, teksty stałe Java nie robić, ponieważ są one bardziej skomplikowane. Dlatego mój ostatni punkt nie jest prawdziwy. Poprawny?
Wszyscy jesteśmy Monica
25
To prawdopodobnie już nie jest poprawne, patrz stackoverflow.com/questions/5143256/ ...
Viktor Dahl
2
Dokumentacja systemu Android nadal odradza używanie wyliczeń: „Wyliczenia często wymagają więcej niż dwa razy więcej pamięci niż stałe statyczne. Należy bezwzględnie unikać używania wyliczeń w systemie Android”. developer.android.com/training/articles/memory.html#Overhead
ThomasW
1
@ SebastianPaaskeTørholm Podany przez Ciebie link (to: developer.android.com/guide/practices/design/… ) nie wyświetla już wskazówki.
programista Androida
14

Liczby całkowite są mniejsze i wymagają mniejszych nakładów, co nadal ma znaczenie na urządzeniach mobilnych.

Russell Steen
źródło
Ponadto mamy teraz dobre narzędzie dla Android Studio i Lint. Mam na myśli adnotacje IntDefi StringDef, które pozwalają na zadeklarowanie jakiegoś typu typedef , więc użycie stałych int jest bardzo wygodne. blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
tak, ale co z modelami Retrofit? (i przypuszczam, że dla innych bibliotek sieciowych) Jak zdefiniowałbyś odpowiedź statusu (np. powodzenie, niepowodzenie, token_expired), aby mapować bezpośrednio do POJO?
mitsest
5

Mój kolega wykonał mały test dotyczący tej sytuacji. Automatycznie wygenerował a classi enumz taką samą ilością „wyliczeń”. Myślę, że wygenerował 30000 wpisów.

Wyniki były następujące:

  • .classza classokoło 1200 KB
  • .classza enumokoło 800 KB

Mam nadzieję, że to komuś pomoże.

prolink007
źródło
Nie sądzę, żeby to był ważny test. Posiadanie 30000 wyliczeń / pól statycznych w jednym miejscu nie jest realistycznym scenariuszem. Będziesz musiał porównać wielkość dużej liczby małych klas / wyliczeń, np. 1000 klas / wyliczeń po 30 właściwości każda. Obstawiam, że całkowity rozmiar będzie zupełnie inny.
Iwo Banas,
7
@Iwo Banas Każdy test jest ważnym testem. Nie powiedziałem, że to odpowie na pytanie. Po prostu zaproponowałem to jako dodatkowe informacje dla każdego, kto może być zainteresowany. A głos negatywny wydaje się bardzo zasłużony, więc dziękuję. -_-
prolink007
Czy to nie pokazuje czegoś przeciwnego? Że enum zużywa mniej? Czy jest to pamięć lub pamięć masowa o pojemności 1200 KB czy 800 KB?
programista Androida