Arbeiten mit Enums in Android

120

Ich bin fast fertig mit einer Berechnungsaktivität, mit der ich in Android für meine App arbeite. Ich versuche, eine Gender-Aufzählung zu erstellen, aber aus irgendeinem Grund, wenn ein Syntaxfehler auftritt, fügen Sie "EnumBody" ein, um die EnumDeclaration abzuschließen.

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

Ich habe es auch ohne das statische {} versucht, aber ich erhalte den gleichen Syntaxfehler.

JMSDEV
quelle
Aufzählungen werden für Leistungsprobleme nicht empfohlen. Verwenden Sie stattdessen primitive Konstanten. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
UPDATE 2019: Aufzählungen können problemlos in Android verwendet werden, da ART DALVIK als Laufzeitumgebung stackoverflow.com/a/56296746/4213436 ersetzt hat . Daher denke ich, dass die meisten Antworten auf diesen Thread irrelevant sind.
JDenais
@JDenais natürlich meinst du den Thread 'du', auf den gerade verwiesen wurde
YoussefDir

Antworten:

343

Wo um alles in der Welt haben Sie diese Syntax gefunden? Java Enums sind sehr einfach, Sie geben nur die Werte an.

public enum Gender {
   MALE,
   FEMALE
}

Wenn Sie möchten, dass sie komplexer sind, können Sie ihnen auf diese Weise Werte hinzufügen.

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;
    }
}

Um dann die Aufzählung zu verwenden, würden Sie ungefähr Folgendes tun:

Gender me = Gender.MALE
Spidy
quelle
11
Ich werde es versuchen, ich habe gesagt, ich war ein absoluter Anfänger
JMSDEV
86
Entschuldigung, das habe ich nicht negativ gemeint. Nur die seltsamste Syntax, die ich je für ein Enum
Spidy
3
Es ist auch hilfreich zu erwähnen, dass Aufzählungen sequentiell sind, sodass Sie .ordinal () für die Aufzählung verwenden können, um den int-Wert zu erhalten.
Kalel Wade
1
Die Syntax in der Frage ist die Art, die man sich bei der Verwendung eines Dekompilers einfallen lassen könnte.
Dan Getz
9
Ich habe so viel über "Wo um alles in der Welt haben Sie diese Syntax gefunden" gelacht. Sagen wie ein Lehrer zu seinem Schüler
Zar E Ahmer
50

Es gab einige Debatten um diesen Streitpunkt, aber selbst in den neuesten Dokumenten schlägt Android vor, dass es keine so gute Idee ist, Aufzählungen in einer Android-Anwendung zu verwenden. Der Grund dafür ist, dass sie mehr Speicher als eine statische Konstantenvariable verbrauchen. Hier ist ein Dokument von einer Seite von 2014, das von der Verwendung von Aufzählungen in einer Android-Anwendung abrät. http://developer.android.com/training/articles/memory.html#Overhead

Ich zitiere:

Beachten Sie den Speicheraufwand

Machen Sie sich mit den Kosten und dem Aufwand der von Ihnen verwendeten Sprache und Bibliotheken vertraut und berücksichtigen Sie diese Informationen beim Entwerfen Ihrer App von Anfang bis Ende. Oft haben Dinge auf der Oberfläche, die harmlos aussehen, tatsächlich einen großen Overhead. Beispiele beinhalten:

  • Aufzählungen erfordern oft mehr als doppelt so viel Speicher wie statische Konstanten. Sie sollten die Verwendung von Aufzählungen unter Android unbedingt vermeiden.

  • Jede Klasse in Java (einschließlich anonymer innerer Klassen) verwendet ungefähr 500 Byte Code.

  • Jede Klasseninstanz hat 12-16 Byte RAM-Overhead.

  • Das Einfügen eines einzelnen Eintrags in eine HashMap erfordert die Zuweisung eines zusätzlichen Eintragsobjekts, das 32 Byte benötigt (siehe vorherigen Abschnitt zu optimierten Datencontainern).

Ein paar Bytes hier und da summieren sich schnell - App-Designs, die klassen- oder objektlastig sind, leiden unter diesem Overhead. Das kann Sie in die schwierige Lage versetzen, eine Heap-Analyse zu betrachten und zu erkennen, dass Ihr Problem viele kleine Objekte sind, die Ihren RAM verbrauchen.

Es gab einige Stellen, an denen sie sagten, dass diese Tipps veraltet und nicht mehr wertvoll sind, aber der Grund, warum sie sie immer wieder wiederholen, muss sein, dass es eine Wahrheit gibt. Das Schreiben einer Android-Anwendung ist etwas, das Sie für eine reibungslose Benutzererfahrung so leicht wie möglich halten sollten. Und jeder Zentimeter Leistung zählt!

Chris
quelle
Es gab einige Orte - könnten Sie einige hinzufügen, wenn Sie sie kennen? weil ich keine finden kann
Krzysztof Skrzynecki
9
Hier bemerkte jemand, dass Informationen zur Verwendung von Ints anstelle von Enums aus den Leistungstipps in der offiziellen Dokumentation entfernt wurden. Außerdem habe ich recherchiert und eine Zusammenfassung auf reddit
Krzysztof Skrzynecki
1
Android-Leistungsmuster: Der Preis von ENUMs (100 Tage von Google Dev)
Afriza N. Arief
Leute, meine Frage ist, wenn Enum eine "schlechte" Praxis ist, warum unterstützt Google diese Funktion von Java mit Android immer noch? :(
Jesús Castro
5
@ JesúsCastro Weil Google sicherstellen möchte, dass Unternehmen mit viel vorhandener Java-Geschäftslogik (die möglicherweise Aufzählungen verwenden) ihre Bibliothek einfach in ein Android-Projekt ablegen und loslegen können.
David Brown
22

Wie von Chris kommentiert, benötigen Enums unter Android viel mehr Speicher, was sich summiert, da sie überall verwendet werden. Sie sollten stattdessen IntDef oder StringDef ausprobieren , die Anmerkungen verwenden, damit der Compiler übergebene Werte überprüft .

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);

Es kann auch als Flags verwendet werden, um eine binäre Komposition (OR / AND-Operationen) zu ermöglichen.

EDIT : Es scheint, dass die Umwandlung von Enums in Ints eine der Standardoptimierungen in Proguard ist .

Nacho Coloma
quelle
3
Ich möchte int-Konstanten direkt in die Annotationsklasse einfügen. So sieht es aus wie normale Aufzählung. Ich habe es hier beschrieben: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
17
public enum Gender {
    MALE,
    FEMALE
}
Gabriel Negut
quelle
9

Laut diesem Video müssen Sie, wenn Sie den ProGuard verwenden, nicht einmal über Leistungsprobleme bei Enums nachdenken !!

Proguard kann in vielen Situationen Enums auf INT-Werte in Ihrem Namen optimieren, sodass Sie wirklich nicht darüber nachdenken oder irgendwelche Arbeiten ausführen müssen.

Hani
quelle
4

Der bevorzugte Ansatz von Android sind int-Konstanten, die mit @IntDef erzwungen werden:

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;
  }
}

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

Anm
quelle