Android: ¿Cómo poner una enumeración en un paquete?


332

¿Cómo se agrega un objeto Enum a un paquete de Android?


11
En mi opinión, ese consejo del personal de Google es malo. Las enumeraciones son muy convenientes y sufren los gastos generales descritos.
ognian

3
puedes volver a visitar las respuestas y aceptar la segunda si crees que podría ser una mejor opción.
philipp

66
Bajo el encabezado "Evitar enumeraciones" en el enlace anterior ahora dice esto: Mitos de rendimiento Las versiones anteriores de este documento hicieron varias afirmaciones engañosas. Nos dirigimos a algunos de ellos aquí.
StackOverflowed

esa sección ya ni siquiera está presente.
Nathaniel D. Waggoner

Respuestas:


726

Las enumeraciones son serializables, por lo que no hay problema.

Dada la siguiente enumeración:

enum YourEnum {
  TYPE1,
  TYPE2
}

Haz:

// put
bundle.putSerializable("key", YourEnum.TYPE1);

// get 
YourEnum yourenum = (YourEnum) bundle.get("key");

Intención:

// put
intent.putExtra("key", yourEnum);

// get
yourEnum = (YourEnum) intent.getSerializableExtra("key");

¿Hay algún problema con este método: guardar: outState.putSerializable("trollData", game.getFunkyTrolls());cargar game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));:?
Moberg

21
Hubiera votado por su respuesta, pero la pregunta era sobre agregar el Enum a un paquete y su respuesta explica cómo agregarlo a una intención ... De acuerdo, es casi lo mismo, pero Alejandro a continuación arregló su respuesta.
Pooks

2
cuando lo usa con Bundle, arrojaClassNotFoundException
Nombre para mostrar

2
esto puede ser súper lento y no se escala a conjuntos de cosas que contienen enumeración, etc. Ver stackoverflow.com/a/5551155/175156
yincrash

1
@yincrash enum usa una serialización personalizada que es bastante rápida. Prueba: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64

164

Sé que esta es una vieja pregunta, pero encontré el mismo problema y me gustaría compartir cómo lo resolví. La clave es lo que dijo Miguel: las enumeraciones son serializables.

Dada la siguiente enumeración:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Poner:

Bundle args = new Bundle();
args.putSerializable("arg", YourEnumType.ENUM_KEY_1);

3
Basado en esto: stackoverflow.com/questions/15521309/… , las enumeraciones personalizadas no son serializables. Por lo tanto, los campos personalizados en una enumeración no se serializarán. Como tratas con esto?
clu

Buena pregunta @clu! Tal vez debería pensar en pasarlo como una cadena como se indica en stackoverflow.com/questions/609860/…
Alejandro Colorado

@clu Al no esperar que los campos personalizados se serialicen. Funciona bien si es solo una enumeración normal como en el código anterior.
bluehallu

@AlejandroColorado ¿qué agrega esto a la respuesta de miguel?
tir38

1
La respuesta de Miguel fue editada en 2015. La respuesta original no decía nada sobre paquetes, solo mostraba un ejemplo de una intención.
Alejandro Colorado

41

Para completar, este es un ejemplo completo de cómo poner y recuperar una enumeración de un paquete.

Dada la siguiente enumeración:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Puedes poner la enumeración en un paquete:

bundle.putSerializable("enum_key", EnumType.ENUM_VALUE_1);

Y recuperar la enumeración:

EnumType enumType = (EnumType)bundle.getSerializable("enum_key");

32

Yo uso kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

luego poner en Intento:

intent.putExtra(KEY_MODE, Mode.MODE_DOWNLOAD.name)

cuando netas para obtener valor:

mode = Mode.valueOf(intent.getStringExtra(KEY_MODE))

66
Esta es una buena respuesta, pero se puede complementar con un método de extensión, lo uso aquí: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden

.namees un camino muy importante
Phan Van Linh

Esto parece mucho más simple que convertir el Enum en un paquete, lo que crearía una mayor complejidad si se trabaja con la biblioteca de base de datos Room de Android .
Adam Hurwitz

@GabrielDeOliveiraRohden, no estoy seguro de que se necesite el método de extensión, ya que parece que solo evita el uso de .namein putString(). Con Kotlin ya está optimizado si se usa .apply. Por ejemplo :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz,

@AdamHurwitz, ¿no es la función de extensión propuesta el punto completo de las funciones de extensión de Kotlins? Te obliga a no cometer errores, ¡es perfecto! Enlace de bundle.putEnum(key, enum) | bundle.getEnum<>(key)
@GabrielDeOliveiraRohden

17

Puede ser mejor pasarlo como una cadena desde myEnumValue.name () y restaurarlo desde YourEnums.valueOf (s), ya que de lo contrario se debe preservar el orden de la enumeración.

Explicación más larga: Convertir de enum ordinal a enum type


1
El orden no importa si la serialización-> deserialización ocurre inmediatamente en tiempo de ejecución, como cuando se llama de una actividad a otra. Podría ser un problema en todos los procesos, como el envío de intenciones de una aplicación a versiones anteriores de la aplicación.
miguel

6

Otra opción:

public enum DataType implements Parcleable {
    SIMPLE, COMPLEX;

    public static final Parcelable.Creator<DataType> CREATOR = new Creator<DataType>() {

        @Override
        public DataType[] newArray(int size) {
            return new DataType[size];
        }

        @Override
        public DataType createFromParcel(Parcel source) {
            return DataType.values()[source.readInt()];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.ordinal());
    }
}

1
Puede usar putSerializable(key, value)/ (Type) getSerializable(key)o putString(key, value.name())/ Type.valueOf(getString(key)), la implementación parcelable aquí es redundante y sin sentido.
Miha_x64

1
Usar Parcelablees una buena solución para almacenar matrices de valores Enum.
RhodanV5500


2

Para Intención puedes usar esta manera:

Intención: kotlin.

PrimeroActividad:

val intent = Intent(context, SecondActivity::class.java)
intent.putExtra("type", typeEnum.A)
startActivity(intent)

Segunda actividad:

override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState) 
     //...
     val type = (intent.extras?.get("type") as? typeEnum.Type?)
}

1

Una cosa a tener en cuenta: si está utilizando bundle.putSerializablepara Bundleque se agregue a una notificación, podría encontrarse con el siguiente problema:

*** Uncaught remote exception!  (Exceptions are not yet supported across processes.)
    java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object.

...

Para evitar esto, puede hacer lo siguiente:

public enum MyEnum {
    TYPE_0(0),
    TYPE_1(1),
    TYPE_2(2);

    private final int code;

    private MyEnum(int code) {
        this.code = navigationOptionLabelResId;
    }

    public int getCode() {
        return code;
    }

    public static MyEnum fromCode(int code) {
        switch(code) {
            case 0:
                return TYPE_0;
            case 1:
                return TYPE_1;
            case 2:
                return TYPE_2;
            default:
                throw new RuntimeException(
                    "Illegal TYPE_0: " + code);
        }
    }
}

Que luego se puede usar así:

// Put
Bundle bundle = new Bundle();
bundle.putInt("key", MyEnum.TYPE_0.getCode());

// Get 
MyEnum myEnum = MyEnum.fromCode(bundle.getInt("key"));

0

De una manera simple, asigne un valor entero a enum

Vea el siguiente ejemplo:

public enum MyEnum {

    TYPE_ONE(1), TYPE_TWO(2), TYPE_THREE(3);

    private int value;

    MyEnum(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

}

Lado del remitente:

Intent nextIntent = new Intent(CurrentActivity.this, NextActivity.class);
nextIntent.putExtra("key_type", MyEnum.TYPE_ONE.getValue());
startActivity(nextIntent);

Lado del receptor:

Bundle mExtras = getIntent().getExtras();
int mType = 0;
if (mExtras != null) {
    mType = mExtras.getInt("key_type", 0);
}

/* OR
    Intent mIntent = getIntent();
    int mType = mIntent.getIntExtra("key_type", 0);
*/

if(mType == MyEnum.TYPE_ONE.getValue())
    Toast.makeText(NextActivity.this, "TypeOne", Toast.LENGTH_SHORT).show();
else if(mType == MyEnum.TYPE_TWO.getValue())
    Toast.makeText(NextActivity.this, "TypeTwo", Toast.LENGTH_SHORT).show();
else if(mType == MyEnum.TYPE_THREE.getValue())
    Toast.makeText(NextActivity.this, "TypeThree", Toast.LENGTH_SHORT).show();
else
    Toast.makeText(NextActivity.this, "Wrong Key", Toast.LENGTH_SHORT).show();

0

Creo que convertir enum a int (para enum normal) y luego configurar en paquete fue la forma más fácil. como este código para la intención:

myIntent.PutExtra("Side", (int)PageType.Fornt);

entonces para verificar el estado:

int type = Intent.GetIntExtra("Side",-1);
if(type == (int)PageType.Fornt)
{
    //To Do
}

¡Pero no funciona para todo tipo de enumeración!


0

He creado una extensión de Koltin:

fun Bundle.putEnum(key: String, enum: Enum<*>) {
    this.putString( key , enum.name )
}

inline fun <reified T: Enum<T>> Intent.getEnumExtra(key:String) : T {
    return enumValueOf( getStringExtra(key) )
}

Crea un paquete y agrega:

Bundle().also {
   it.putEnum( "KEY" , ENUM_CLAS.ITEM )
}

y obten:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.