Trabajar con Enums en Android

120

Casi he terminado con una actividad de cálculo con la que estoy trabajando en Android para mi aplicación. Intento crear una enumeración de género, pero por alguna razón obtengo un error de sintaxis, inserte "EnumBody" para completar 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;
    }
}

También lo probé sin el {} estático pero obtengo el mismo error de sintaxis.

JMSDEV
fuente
No se recomiendan las enumeraciones para problemas de rendimiento, use constantes primitivas en su lugar. youtube.com/watch?v=Hzs6OBcvNQE
Myke Dev
ACTUALIZACIÓN 2019: Las enumeraciones están bien para usar en Android ya que ART reemplazó a DALVIK como entorno de ejecución stackoverflow.com/a/56296746/4213436 . Por lo tanto, creo que la mayoría de las respuestas en este hilo son irrelevantes.
JDenais
@JDenais, por supuesto, te refieres al hilo 'tú' que acabas de mencionar
YoussefDir

Respuestas:

343

¿Dónde diablos encontraste esta sintaxis? Las enumeraciones de Java son muy simples, solo especifique los valores.

public enum Gender {
   MALE,
   FEMALE
}

Si desea que sean más complejos, puede agregarles valores como este.

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

Luego, para usar la enumeración, haría algo como esto:

Gender me = Gender.MALE
Spidy
fuente
12
Lo intentaré, dije que era un principiante absoluto
JMSDEV
87
Lo siento, no quise decir eso negativamente. Simplemente la sintaxis más extraña que he visto para un Enum
Spidy
4
También es útil mencionar que las enumeraciones son secuenciales para que pueda usar .ordinal () en la enumeración para obtener el valor int.
Kalel Wade
1
La sintaxis de la pregunta es la que se podría obtener al usar un descompilador.
Dan Getz
9
Me reí mucho en "¿Dónde diablos encontraste esta sintaxis?". Diciendo como un maestro a su alumno
Zar E Ahmer
50

Ha habido cierto debate en torno a este punto de discusión, pero incluso en los documentos más recientes, Android sugiere que no es una buena idea usar enumeraciones en una aplicación de Android. La razón es porque consumen más memoria que una variable de constantes estáticas. Aquí hay un documento de una página de 2014 que desaconseja el uso de enumeraciones en una aplicación de Android. http://developer.android.com/training/articles/memory.html#Overhead

Yo cito:

Sea consciente de la sobrecarga de memoria

Conozca el costo y los gastos generales del idioma y las bibliotecas que está utilizando, y tenga en cuenta esta información cuando diseñe su aplicación, de principio a fin. A menudo, las cosas en la superficie que parecen inocuas pueden de hecho tener una gran cantidad de gastos generales. Ejemplos incluyen:

  • Las enumeraciones a menudo requieren más del doble de memoria que las constantes estáticas. Debes evitar estrictamente el uso de enumeraciones en Android.

  • Cada clase en Java (incluidas las clases internas anónimas) utiliza aproximadamente 500 bytes de código.

  • Cada instancia de clase tiene 12-16 bytes de RAM.

  • Poner una sola entrada en un HashMap requiere la asignación de un objeto de entrada adicional que ocupa 32 bytes (consulte la sección anterior sobre contenedores de datos optimizados).

Unos pocos bytes aquí y allá se suman rápidamente: los diseños de aplicaciones que son pesados ​​en clases o en objetos sufrirán esta sobrecarga. Eso puede dejarlo en la difícil posición de mirar un análisis de montón y darse cuenta de que su problema es que hay muchos objetos pequeños que usan su RAM.

Ha habido algunos lugares donde dicen que estos consejos están desactualizados y ya no son valiosos, pero la razón por la que siguen repitiéndolos, debe ser que hay algo de verdad en ellos. Escribir una aplicación de Android es algo que debe mantener lo más ligero posible para una experiencia de usuario fluida. ¡Y cada centímetro de rendimiento cuenta!

Chris
fuente
Ha habido algunos lugares , ¿podría agregar algunos si los conoce? porque no puedo encontrar ninguno
Krzysztof Skrzynecki
9
Aquí alguien notó que la información sobre el uso de ints en lugar de enums se eliminó de Performance Tips en la documentación oficial. Además, hice una investigación y publiqué un resumen en reddit
Krzysztof Skrzynecki
1
Patrones de rendimiento de Android: el precio de ENUM (100 días de desarrollo de Google)
Afriza N. Arief
Chicos, mi pregunta es si Enum es una práctica "mala", ¿por qué Google todavía admite esta función de Java con Android? :(
Jesús Castro
5
@ JesúsCastro Porque Google quiere asegurarse de que las empresas con mucha lógica empresarial Java existente (que puede estar usando enumeraciones) puedan simplemente colocar su biblioteca en un proyecto de Android y listo.
David Brown
22

Como comentó Chris, las enumeraciones requieren mucha más memoria en Android que se suma a medida que se siguen usando en todas partes. En su lugar, debería probar IntDef o StringDef , que utilizan anotaciones para que el compilador valide los valores pasados.

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

También se puede utilizar como banderas, lo que permite la composición binaria (operaciones OR / AND).

EDITAR : Parece que la transformación de enumeraciones en ints es una de las optimizaciones predeterminadas en Proguard .

Nacho Coloma
fuente
3
Me gusta colocar constantes int directamente en la clase de anotación. Por lo tanto, parece una enumeración regular. Lo describí aquí: blog.shamanland.com/2016/02/int-string-enum.html
Oleksii K.
17
public enum Gender {
    MALE,
    FEMALE
}
Gabriel Negut
fuente
9

De acuerdo con este video, si usa ProGuard, ¡ni siquiera necesita pensar en los problemas de rendimiento de Enums!

Proguard puede, en muchas situaciones, optimizar Enums a valores INT en su nombre, por lo que realmente no necesita pensar en ello ni hacer ningún trabajo.

Hani
fuente
4

El enfoque preferido de Android son las constantes int aplicadas con @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
fuente