Praca z wyliczeniami w systemie Android

120

Prawie skończyłem z obliczeniami, z którymi pracuję w Androidzie dla mojej aplikacji. Próbuję utworzyć wyliczenie płci, ale z jakiegoś powodu otrzymuję pojawia błąd składni, wstaw "EnumBody", aby uzupełnić EnumDeclaration.

public static enum Gender
{
    static
    {
        Female = new Gender("Female", 1);
        Gender[] arrayOfGender = new Gender[2];
        arrayOfGender[0] = Male;
        arrayOfGender[1] = Female;
        ENUM$VALUES = arrayOfGender;
    }
}

Próbowałem również bez statycznego {}, ale otrzymuję ten sam błąd składni.

JMSDEV
źródło
Wyliczenia nie są zalecane w przypadku problemów z wydajnością, zamiast tego użyj stałych pierwotnych. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
UPDATE 2019: wyliczenia można używać w systemie Android, ponieważ ART zastąpił DALVIK jako środowisko wykonawcze stackoverflow.com/a/56296746/4213436 . Dlatego myślę, że większość odpowiedzi w tym wątku jest nieistotna.
JDenais
@JDenais oczywiście masz na myśli wątek `` ty '', do którego właśnie się
odwołałeś

Odpowiedzi:

343

Gdzie na ziemi znalazłeś tę składnię? Wyliczenia Java są bardzo proste, wystarczy określić wartości.

public enum Gender {
   MALE,
   FEMALE
}

Jeśli chcesz, aby były bardziej złożone, możesz dodać do nich wartości w ten sposób.

public enum Gender {
    MALE("Male", 0),
    FEMALE("Female", 1);

    private String stringValue;
    private int intValue;
    private Gender(String toString, int value) {
        stringValue = toString;
        intValue = value;
    }

    @Override
    public String toString() {
        return stringValue;
    }
}

Następnie, aby użyć wyliczenia, zrobiłbyś coś takiego:

Gender me = Gender.MALE
Spidy
źródło
12
Spróbuję, powiedziałem, że jestem absolutnym początkującym
JMSDEV
87
Przepraszam, nie miałem na myśli tego negatywnie. Po prostu najdziwniejsza składnia, jaką kiedykolwiek widziałem dla Enum
Spidy
4
Warto również wspomnieć, że wyliczenia są sekwencyjne, więc możesz użyć .ordinal () na wyliczeniu, aby uzyskać wartość int.
Kalel Wade,
1
Składnia w pytaniu jest taka, jaką można wymyślić przy użyciu dekompilatora.
Dan Getz,
9
Śmiałem się bardzo przy „Gdzie na ziemi znalazłeś tę składnię”. Mówiąc jak nauczyciel do swojego ucznia
Zar E Ahmer
50

Odbyła się pewna debata na temat tego punktu spornego, ale nawet w najnowszych dokumentach android sugeruje, że używanie wyliczeń w aplikacjach na Androida nie jest dobrym pomysłem. Powodem jest to, że zużywają więcej pamięci niż zmienna statyczna. Oto dokument ze strony z 2014 r., Który odradza stosowanie wyliczeń w aplikacji na Androida. http://developer.android.com/training/articles/memory.html#Overhead

Cytuję:

Uważaj na obciążenie pamięci

Miej wiedzę na temat kosztów i narzutów związanych z językiem i bibliotekami, z których korzystasz, i pamiętaj o tych informacjach podczas projektowania aplikacji, od początku do końca. Często rzeczy na powierzchni, które wyglądają nieszkodliwie, mogą w rzeczywistości wiązać się z dużym obciążeniem. Przykłady obejmują:

  • 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.

  • Każda klasa w Javie (w tym anonimowe klasy wewnętrzne) wykorzystuje około 500 bajtów kodu.

  • Każda instancja klasy ma 12-16 bajtów pamięci RAM.

  • Umieszczenie pojedynczego wpisu w HashMap wymaga przydzielenia dodatkowego obiektu wpisu, który zajmuje 32 bajty (zobacz poprzednią sekcję o zoptymalizowanych kontenerach danych).

Kilka bajtów tu i ówdzie szybko się sumuje - projekty aplikacji, które są obciążone klasami lub obiektami, ucierpią z powodu tego narzutu. To może postawić cię w trudnej sytuacji, gdy spojrzysz na analizę sterty i zdasz sobie sprawę, że twój problem to wiele małych obiektów zużywających pamięć RAM.

Były miejsca, w których mówią, że te wskazówki są przestarzałe i nie są już wartościowe, ale powodem, dla którego ciągle je powtarzają, musi być trochę prawdy. Pisanie aplikacji na Androida to coś, co powinieneś zachować jak najmniejszą wagę, aby zapewnić płynną obsługę. I liczy się każdy centymetr wydajności!

Chris
źródło
Było kilka miejsc - czy możesz je dodać, jeśli je znasz? bo nie mogę znaleźć żadnego
Krzysztof Skrzynecki
9
Tutaj ktoś zauważył, że informacje o używaniu intów zamiast wyliczeń zostały usunięte z porad dotyczących wydajności w oficjalnej dokumentacji. Ponadto przeprowadziłem badania i zamieściłem podsumowanie na reddicie
Krzysztof Skrzynecki
1
Wzorce wydajności Androida: cena ENUM (100 dni Google Dev)
Afriza N. Arief
Chłopaki, moje pytanie brzmi, jeśli Enum jest „złą” praktyką, dlaczego Google nadal obsługuje tę funkcję Javy z Androidem? :(
Jesús Castro
5
@ JesúsCastro Ponieważ Google chce mieć pewność, że firmy z dużą ilością istniejącej logiki biznesowej języka Java (które mogą używać wyliczeń) mogą po prostu przenieść swoją bibliotekę do projektu na Androida i odejść.
David Brown
22

Jak skomentował Chris, wyliczenia wymagają znacznie więcej pamięci w systemie Android, co sumuje się, ponieważ są używane wszędzie. Zamiast tego powinieneś wypróbować IntDef lub StringDef , które używają adnotacji, aby kompilator weryfikował przekazane wartości.

public abstract class ActionBar {
...
@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;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

Może być również używany jako flagi, pozwalając na składanie binarne (operacje OR / AND).

EDYCJA : Wygląda na to, że przekształcanie wyliczeń w wartości typu int jest jedną z domyślnych optymalizacji w Proguard .

Nacho Coloma
źródło
3
Lubię umieszczać stałe int bezpośrednio w klasie adnotacji. W ten sposób wygląda jak zwykłe wyliczenie. Opisałem to tutaj: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
17
public enum Gender {
    MALE,
    FEMALE
}
Gabriel Negut
źródło
9

Zgodnie z tym filmem, jeśli używasz ProGuard, nie musisz nawet myśleć o problemach z wydajnością Enums !!

Proguard może w wielu sytuacjach zoptymalizować wyliczenia do wartości INT w Twoim imieniu, więc naprawdę nie musisz o tym myśleć ani wykonywać żadnej pracy.

Hani
źródło
4

Preferowanym podejściem Androida są stałe int wymuszane za pomocą @IntDef:

public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;

@Retention(RetentionPolicy.SOURCE)
@IntDef ({GENDER_MALE, GENDER_FEMALE})
public @interface Gender{}

// Example usage...
void exampleFunc(@Gender int gender) {
  switch(gender) {
  case GENDER_MALE:

     break;
  case GENDER_FEMALE:
     // TODO
     break;
  }
}

Dokumenty: https://developer.android.com/studio/write/annotations.html#enum-annotations

Anm
źródło