Travailler avec des énumérations dans Android

120

J'ai presque terminé avec une activité de calcul avec laquelle je travaille dans Android pour mon application. J'essaie de créer un Gender Enum, mais pour une raison quelconque , j'obtiens une erreur de syntaxe, insérez "EnumBody" pour terminer 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;
    }
}

Je l'ai également essayé sans le static {} mais j'obtiens la même erreur de syntaxe.

JMSDEV
la source
Les énumérations ne sont pas recommandées pour les problèmes de performances, utilisez plutôt des constantes primitives. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
MISE À JOUR 2019: Les énumérations peuvent être utilisées dans Android puisque ART a remplacé DALVIK comme environnement d'exécution stackoverflow.com/a/56296746/4213436 . Par conséquent, je pense que la plupart des réponses sur ce fil ne sont pas pertinentes.
JDenais
@JDenais bien sûr, vous voulez dire le fil `` vous '' venez de faire référence
YoussefDir

Réponses:

343

Où diable avez-vous trouvé cette syntaxe? Les énumérations Java sont très simples, il vous suffit de spécifier les valeurs.

public enum Gender {
   MALE,
   FEMALE
}

Si vous voulez qu'ils soient plus complexes, vous pouvez leur ajouter des valeurs comme ceci.

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

Ensuite, pour utiliser l'énumération, vous feriez quelque chose comme ceci:

Gender me = Gender.MALE
Spidy
la source
12
Je vais essayer, j'ai dit que j'étais un débutant absolu
JMSDEV
87
Désolé, je ne voulais pas dire cela négativement. Juste la syntaxe la plus étrange que j'ai jamais vue pour un Enum
Spidy
4
Il est également utile de mentionner que les énumérations sont séquentielles afin que vous puissiez utiliser .ordinal () sur l'enum pour obtenir la valeur int.
Kalel Wade
1
La syntaxe de la question est celle que l'on pourrait trouver en utilisant un décompilateur.
Dan Getz
9
J'ai tellement ri sur "Où diable avez-vous trouvé cette syntaxe". Dire comme un enseignant à son élève
Zar E Ahmer
50

Il y a eu un débat autour de ce point de discorde, mais même dans les documents les plus récents, Android suggère que ce n'est pas une si bonne idée d'utiliser des énumérations dans une application Android. La raison en est qu'ils utilisent plus de mémoire qu'une variable de constantes statiques. Voici un document d'une page de 2014 qui déconseille l'utilisation d'énumérations dans une application Android. http://developer.android.com/training/articles/memory.html#Overhead

Je cite:

Soyez conscient de la surcharge de la mémoire

Soyez bien informé sur le coût et les frais généraux du langage et des bibliothèques que vous utilisez, et gardez ces informations à l'esprit lorsque vous concevez votre application, du début à la fin. Souvent, des choses en surface qui semblent inoffensives peuvent en fait avoir une grande charge de travail. Les exemples comprennent:

  • Les énumérations nécessitent souvent plus de deux fois plus de mémoire que les constantes statiques. Vous devez strictement éviter d'utiliser des énumérations sur Android.

  • Chaque classe en Java (y compris les classes internes anonymes) utilise environ 500 octets de code.

  • Chaque instance de classe a 12 à 16 octets de surcharge de RAM.

  • Mettre une seule entrée dans un HashMap nécessite l'allocation d'un objet d'entrée supplémentaire qui prend 32 octets (voir la section précédente sur les conteneurs de données optimisés).

Quelques octets ici et là s'additionnent rapidement - les conceptions d'applications qui sont lourdes en classes ou en objets souffriront de cette surcharge. Cela peut vous laisser dans la position difficile de regarder une analyse de tas et de réaliser que votre problème est que beaucoup de petits objets utilisent votre RAM.

Il y a eu des endroits où ils disent que ces conseils sont dépassés et n'ont plus de valeur, mais la raison pour laquelle ils continuent de le répéter, c'est qu'il y a du vrai. L'écriture d'une application Android est quelque chose que vous devez garder aussi léger que possible pour une expérience utilisateur fluide. Et chaque petit centimètre de performance compte!

Chris
la source
Il y a eu des endroits - pourriez-vous en ajouter si vous les connaissez? parce que je n'en trouve pas
Krzysztof Skrzynecki
9
Ici, quelqu'un a remarqué que les informations sur l'utilisation des ints au lieu des enums ont été supprimées des conseils de performance dans la documentation officielle. De plus, j'ai fait des recherches et publié un résumé sur reddit
Krzysztof Skrzynecki
1
Modèles de performances Android: le prix des ENUM (100 jours de Google Dev)
Afriza N.Arief
Les gars, ma question est si Enum est une "mauvaise" pratique, pourquoi Google prend-il toujours en charge cette fonctionnalité de Java avec Android? :(
Jesús Castro
5
@ JesúsCastro Parce que Google veut s'assurer que les entreprises ayant beaucoup de logique métier Java existante (qui utilisent peut-être des énumérations) puissent simplement déposer leur bibliothèque dans un projet Android et partir.
David Brown
22

Comme l'a commenté Chris, les énumérations nécessitent beaucoup plus de mémoire sur Android, car elles continuent d'être utilisées partout. Vous devriez plutôt essayer IntDef ou StringDef , qui utilisent des annotations afin que le compilateur valide les valeurs passées.

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

Il peut également être utilisé comme indicateur, permettant une composition binaire (opérations OR / AND).

EDIT : Il semble que la transformation des énumérations en entiers soit l' une des optimisations par défaut de Proguard .

Nacho Coloma
la source
3
J'aime placer des constantes int directement dans la classe d'annotation. Cela ressemble donc à une énumération régulière. Je l'ai décrit ici: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
17
public enum Gender {
    MALE,
    FEMALE
}
Gabriel Negut
la source
9

Selon cette vidéo, si vous utilisez le ProGuard, vous n'avez même pas besoin de penser aux problèmes de performances d'Enums !!

Proguard peut dans de nombreuses situations optimiser les Enums aux valeurs INT en votre nom, vous n'avez donc vraiment pas besoin d'y penser ou de faire du travail.

Hani
la source
4

L'approche préférée d'Android est les constantes int appliquées avec @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;
  }
}

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

Anm
la source