Trabalhando com Enums no Android

120

Estou quase terminando uma atividade de cálculo com a qual estou trabalhando no Android para meu aplicativo. Tento criar um Enum de gênero, mas por algum motivo, obtendo um erro de sintaxe, insira "EnumBody" para concluir 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;
    }
}

Eu também tentei sem o {} estático, mas recebo o mesmo erro de sintaxe.

JMSDEV
fonte
Enums não são recomendados para problemas de desempenho; em vez disso, use constantes primitivas. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
ATUALIZAÇÃO 2019: Enums podem ser usados ​​no Android, pois o ART substituiu o DALVIK como ambiente de tempo de execução stackoverflow.com/a/56296746/4213436 . Portanto, acho que a maioria das respostas neste tópico são irrelevantes.
JDenais de
@JDenais, claro, você quer dizer o tópico 'você' que acabou de fazer referência
YoussefDir,

Respostas:

343

Onde diabos você encontrou essa sintaxe? Java Enums são muito simples, você apenas especifica os valores.

public enum Gender {
   MALE,
   FEMALE
}

Se você quiser que eles sejam mais complexos, você pode adicionar valores a eles assim.

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

Então, para usar o enum, você faria algo assim:

Gender me = Gender.MALE
Spidy
fonte
12
Vou tentar, eu disse que era um iniciante absoluto
JMSDEV
87
Desculpe, eu não quis dizer isso de forma negativa. A sintaxe mais estranha que já vi para um Enum
Spidy
4
Também é útil mencionar que os enums são sequenciais para que você possa usar .ordinal () no enum para obter o valor int.
Kalel Wade
1
A sintaxe em questão é o tipo que se pode imaginar usando um descompilador.
Dan Getz
9
Eu ri muito em "Onde diabos você encontrou essa sintaxe". Dizendo como um professor para seu aluno
Zar E Ahmer
50

Tem havido algum debate em torno desse ponto de discórdia, mas mesmo nos documentos mais recentes, o android sugere que não é uma boa ideia usar enums em um aplicativo Android. A razão é porque eles usam mais memória do que uma variável constante estática. Aqui está um documento de uma página de 2014 que desaconselha o uso de enums em um aplicativo Android. http://developer.android.com/training/articles/memory.html#Overhead

Eu cito:

Esteja ciente da sobrecarga de memória

Esteja informado sobre o custo e a sobrecarga da linguagem e das bibliotecas que você está usando e tenha essas informações em mente ao projetar seu aplicativo, do início ao fim. Freqüentemente, coisas na superfície que parecem inócuas podem na verdade ter uma grande sobrecarga. Exemplos incluem:

  • Os enums geralmente requerem mais do que o dobro de memória do que as constantes estáticas. Você deve evitar estritamente o uso de enums no Android.

  • Cada classe em Java (incluindo classes internas anônimas) usa cerca de 500 bytes de código.

  • Cada instância de classe tem 12-16 bytes de sobrecarga de RAM.

  • Colocar uma única entrada em um HashMap requer a alocação de um objeto de entrada adicional que leva 32 bytes (consulte a seção anterior sobre contêineres de dados otimizados).

Alguns bytes aqui e ali rapidamente se somam - designs de aplicativos que são pesados ​​em classes ou objetos sofrerão com essa sobrecarga. Isso pode deixá-lo na difícil posição de olhar para uma análise de heap e perceber que seu problema são muitos objetos pequenos usando sua RAM.

Tem havido alguns lugares onde eles dizem que essas dicas estão desatualizadas e não têm mais valor, mas a razão pela qual eles continuam repetindo isso deve ser que há alguma verdade nisso. Escrever um aplicativo Android é algo que você deve manter o mais leve possível para uma experiência de usuário tranquila. E cada centímetro de desempenho conta!

Chris
fonte
Houve alguns lugares - você poderia adicionar alguns se os conhecesse? porque não consigo encontrar nenhum
Krzysztof Skrzynecki
9
Aqui, alguém notou que as informações sobre o uso de ints em vez de enums foram removidas das Dicas de desempenho na documentação oficial. Além disso, fiz uma pesquisa e postei um resumo no reddit
Krzysztof Skrzynecki
1
Padrões de desempenho do Android: o preço dos ENUMs (100 dias de Google Dev)
Afriza N. Arief
Pessoal, minha dúvida é se Enum é uma prática "ruim", por que o Google ainda suporta esse recurso de Java com Android? :(
Jesús Castro
5
@ JesúsCastro Porque o Google deseja garantir que as empresas com muita lógica de negócios Java existente (que podem estar usando enums) possam simplesmente colocar sua biblioteca em um projeto Android e pronto.
David Brown
22

Conforme comentado por Chris, enums requerem muito mais memória no Android, o que aumenta à medida que são usados ​​em todos os lugares. Você deve tentar IntDef ou StringDef , que usam anotações para que o compilador valide os valores passados.

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

Ele também pode ser usado como sinalizadores, permitindo a composição binária (operações OR / AND).

EDIT : Parece que transformar enums em ints é uma das otimizações padrão no Proguard .

Nacho Coloma
fonte
3
Gosto de colocar constantes int diretamente na classe de anotação. Portanto, parece enum regular. Eu o descrevi aqui: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
17
public enum Gender {
    MALE,
    FEMALE
}
Gabriel Negut
fonte
9

De acordo com este vídeo, se você usar o ProGuard, você não precisa nem pensar nos problemas de desempenho do Enums !!

O Proguard pode, em muitas situações, otimizar Enums para valores INT em seu nome, então realmente não precisa pensar sobre isso ou fazer qualquer trabalho.

Hani
fonte
4

A abordagem preferida do Android são constantes int aplicadas com @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;
  }
}

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

Anm
fonte