Android: come mettere un Enum in un pacchetto?


332

Come si aggiunge un oggetto Enum a un pacchetto Android?


11
A mio avviso, i consigli dello staff di Google non vanno bene. Gli enum sono molto convenienti e vale la pena soffrire per il sovraccarico descritto.
— ognian,

3
puoi rivisitare le risposte e accettare la seconda se pensi che potrebbe essere una scelta migliore.
— philipp,

6
Sotto l'intestazione "Evitare enumerazioni" nel link sopra riportato ora dice questo: Miti delle prestazioni Le versioni precedenti di questo documento presentavano varie affermazioni fuorvianti. Ne affrontiamo alcuni qui.
— StackOverflow

quella sezione non è nemmeno più presente.
— Nathaniel D. Wagoner,

Risposte:


726

Gli enumeratori sono serializzabili, quindi non ci sono problemi.

Dato il seguente enum:

enum YourEnum {
  TYPE1,
  TYPE2
}

Bundle:

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

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

Intent:

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

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

C'è qualcosa di sbagliato in questo metodo: salvataggio: outState.putSerializable("trollData", game.getFunkyTrolls());caricamento game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));:?
— Moberg,

21
Avrei votato a favore della tua risposta, ma la domanda riguardava l'aggiunta dell'Enum a un pacchetto e la tua risposta spiega come aggiungerlo a un Intento ... Concesso è quasi la stessa cosa, ma Alejandro sotto ha corretto la tua risposta.
— Pooks,

2
quando lo si utilizza con Bundle, generaClassNotFoundException
— Visualizza nome

2
questo può essere super lento e non si adatta alle matrici di cose che contengono enum, ecc See stackoverflow.com/a/5551155/175156
— yincrash

1
@yincrash enum usa una serializzazione personalizzata che è abbastanza veloce. Prova: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
— Miha_x64

164

So che questa è una vecchia domanda, ma sono arrivato con lo stesso problema e vorrei condividere come l'ho risolto. La chiave è ciò che Miguel ha detto: gli Enum sono serializzabili.

Dato il seguente enum:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Mettere:

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

3
Sulla base di questo: stackoverflow.com/questions/15521309/… , gli Enum personalizzati non sono serializzabili. Quindi i campi personalizzati in un Enum non verranno serializzati. come lo gestisci?
— clu

Bella domanda @clu! Forse allora dovresti pensare di passarlo come una stringa come indicato in stackoverflow.com/questions/609860/…
— Alejandro Colorado,

@clu Non prevedendo la serializzazione dei campi personalizzati. Funziona bene se è solo un enum normale come nel codice sopra.
— Bluehallu,

@AlejandroColorado cosa aggiunge questo alla risposta di Miguel?
— tir38,

1
La risposta di Miguel è stata modificata nel 2015. La risposta originale non diceva nulla sui fasci, mostrava solo un esempio di intento.
— Alejandro Colorado,

41

Per completezza, questo è un esempio completo di come inserire e recuperare un enum da un pacchetto.

Dato il seguente enum:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Puoi mettere l'enum in un bundle:

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

E riprenditi l'enum:

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

32

Uso kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

quindi metti in Intento:

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

quando fai rete per ottenere valore:

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

6
Questa è una buona risposta, ma può essere integrata con un metodo di estensione, lo uso qui: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
— Gabriel De Oliveira Rohden

.nameè un percorso molto importante
— Phan Van Linh,

Questo sembra molto più semplice che trasformare Enum in un pacchetto, il che creerebbe ulteriore complessità se si lavora con la libreria di database Room di Android .
— Adam Hurwitz,

@GabrielDeOliveiraRohden, non sono sicuro che il metodo di estensione sia necessario in quanto sembra evitare solo l'uso di .namein putString(). Con Kotlin è già ottimizzato se utilizzato .apply. Ad esempio :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
— Adam Hurwitz,

@AdamHurwitz, la funzione di estensione proposta non è l'intero punto delle funzioni di estensione di Kotlins? Ti costringe a non commettere errori, è perfetto! Link di bundle.putEnum(key, enum) | bundle.getEnum<>(key)
— @GabrielDeOliveiraRohden

17

Potrebbe essere meglio passarlo come stringa da myEnumValue.name () e ripristinarlo da YourEnums.valueOf (s), altrimenti è necessario preservare l'ordinamento dell'enum!

Spiegazione più lunga: Converti da enum ordinal a enum type


1
L'ordinamento non importa se la serializzazione-> deserializzazione avviene immediatamente in fase di esecuzione, ad esempio quando si chiama da un'attività a un'altra. Potrebbe essere un problema attraverso processi come l'invio di Intenti da un'app a una versione precedente dell'app.
— miguel,

6

Un'altra opzione:

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
Puoi usare putSerializable(key, value)/ (Type) getSerializable(key)o putString(key, value.name())/ Type.valueOf(getString(key)), l'implementazione parcelabile qui è ridondante e senza senso.
— Miha_x64,

1
L'utilizzo Parcelableè una buona soluzione per archiviare le matrici di valori Enum.
— RhodanV5500,


2

Per Intent puoi usare in questo modo:

Intento: kotlin

FirstActivity:

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

SecondActivity:

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

1

Una cosa da tenere presente: se si utilizza bundle.putSerializableper Bundleessere aggiunto a una notifica, è possibile che si verifichi il seguente problema:

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

...

Per aggirare questo, è possibile effettuare le seguenti operazioni:

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

Che può quindi essere utilizzato in questo modo:

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

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

0

Un modo semplice, assegnare il valore intero a enum

Vedi il seguente esempio:

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

}

Lato mittente:

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

Lato ricevitore:

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

Penso che convertire enum in int (per enum normale) e poi impostare su bundle sia stato il modo più semplice. come questo codice per intento:

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

quindi per lo stato di controllo:

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

ma non funziona per tutti i tipi di enum!


0

Ho creato un'estensione 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 pacchetto e aggiungi:

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

e prendi:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.