Android: Wie füge ich eine Aufzählung in ein Bundle ein?


332

Wie fügt man einem Android-Bundle ein Enum-Objekt hinzu?


11
Meiner Meinung nach ist der Rat von Google-Mitarbeitern schlecht. Aufzählungen sind sehr praktisch und das Leiden des beschriebenen Overheads ist es wert.
Ognian

3
Können Sie die Antworten noch einmal überprüfen und die zweite akzeptieren, wenn Sie der Meinung sind, dass dies eine bessere Wahl ist?
Philipp

6
Unter der Überschrift "Vermeiden von Aufzählungen" im obigen Link heißt es nun: Leistungsmythen In früheren Versionen dieses Dokuments wurden verschiedene irreführende Behauptungen aufgestellt. Wir sprechen hier einige davon an.
StackOverflowed

Dieser Abschnitt ist nicht einmal mehr vorhanden.
Nathaniel D. Waggoner

Antworten:


726

Aufzählungen sind serialisierbar, daher gibt es kein Problem.

Angesichts der folgenden Aufzählung:

enum YourEnum {
  TYPE1,
  TYPE2
}

Bündeln:

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

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

Absicht:

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

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

Stimmt etwas mit dieser Methode nicht: Speichern: outState.putSerializable("trollData", game.getFunkyTrolls());Laden : game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));?
Moberg

21
Ich hätte für Ihre Antwort gestimmt, aber bei der Frage ging es darum, die Aufzählung zu einem Bundle hinzuzufügen, und in Ihrer Antwort wird erklärt, wie Sie sie zu einer Absicht hinzufügen können ... Zugegeben, es ist fast dasselbe, aber Alejandro unten hat Ihre Antwort korrigiert.
Pooks

2
wenn es mit Bundle verwendet wird, wirft esClassNotFoundException
Anzeigename

2
Dies kann sehr langsam sein und lässt sich nicht auf Arrays von Dingen skalieren, die Enum usw. enthalten. Siehe stackoverflow.com/a/5551155/175156
yincrash

1
@yincrash enum verwendet eine benutzerdefinierte Serialisierung, die recht schnell ist. Beweis: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64

164

Ich weiß, dass dies eine alte Frage ist, aber ich hatte das gleiche Problem und möchte mitteilen, wie ich es gelöst habe. Der Schlüssel ist, was Miguel sagte: Aufzählungen sind serialisierbar.

Angesichts der folgenden Aufzählung:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Stellen:

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

3
Basierend darauf: stackoverflow.com/questions/15521309/… sind benutzerdefinierte Aufzählungen nicht serialisierbar. Daher werden die benutzerdefinierten Felder in einer Aufzählung nicht serialisiert. Wie gehst du damit um?
Clu

Schöne Frage @clu! Vielleicht sollten Sie dann darüber nachdenken, es als Zeichenfolge zu übergeben, wie in stackoverflow.com/questions/609860/… angegeben
Alejandro Colorado

@clu Indem nicht erwartet wird, dass benutzerdefinierte Felder serialisiert werden. Es funktioniert gut, wenn es nur eine normale Aufzählung wie im obigen Code ist.
Bluehallu

@AlejandroColorado Was trägt dies zu Miguels Antwort bei?
Tir38

1
Miguels Antwort wurde 2015 bearbeitet. Die ursprüngliche Antwort sagte nichts über Bündel aus, sondern zeigte nur ein Beispiel für eine Absicht.
Alejandro Colorado

41

Der Vollständigkeit halber ist dies ein vollständiges Beispiel dafür, wie Sie eine Enumeration aus einem Bundle einfügen und zurückerhalten.

Angesichts der folgenden Aufzählung:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Sie können die Aufzählung in ein Bündel packen:

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

Und hol die Aufzählung zurück:

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

32

Ich benutze Kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

dann in Absicht setzen:

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

wenn Sie netto, um Wert zu erhalten:

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

6
Dies ist eine gute Antwort, aber sie kann durch eine Erweiterungsmethode ergänzt werden. Ich verwende diese hier: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden

.nameist sehr wichtiger Weg
Phan Van Linh

Dies scheint viel einfacher zu sein, als die Aufzählung in ein Paket umzuwandeln, was bei der Arbeit mit der Room- Datenbankbibliothek von Android zu einer weiteren Komplexität führen würde .
Adam Hurwitz

@GabrielDeOliveiraRohden, ich bin nicht sicher, ob die Erweiterungsmethode benötigt wird, da sie nur die Verwendung des .nameIn zu vermeiden scheint putString(). Mit Kotlin ist es bereits optimiert, wenn es verwendet wird .apply. Zum Beispiel :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz

@AdamHurwitz, ist die vorgeschlagene Erweiterungsfunktion nicht der gesamte Punkt der Kotlins-Erweiterungsfunktionen? Es zwingt dich, keine Fehler zu machen, es ist perfekt! @ GabrielDeOliveiraRohdens Linkbundle.putEnum(key, enum) | bundle.getEnum<>(key)
Yokich

17

Es ist möglicherweise besser, es als Zeichenfolge aus myEnumValue.name () zu übergeben und aus YourEnums.valueOf (s) wiederherzustellen, da sonst die Reihenfolge der Aufzählung beibehalten werden muss!

Längere Erklärung: Konvertieren Sie von der Ordnungszahl in den Aufzählungstyp


1
Die Reihenfolge spielt keine Rolle, wenn die Serialisierung-> Deserialisierung sofort zur Laufzeit erfolgt, z. B. beim Aufrufen von einer Aktivität zu einer anderen. Es kann ein Problem bei Prozessen sein, z. B. beim Senden von Absichten von einer App an eine ältere Version der App.
Miguel

6

Andere Option:

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
Sie können entweder putSerializable(key, value)/ (Type) getSerializable(key)oder putString(key, value.name())/ verwenden Type.valueOf(getString(key)). Die Implementierung von Parcelable ist hier redundant und unsinnig.
Miha_x64

1
Die Verwendung Parcelableist eine gute Lösung zum Speichern von Arrays mit Enum-Werten.
RhodanV5500


2

Für Intent können Sie Folgendes verwenden:

Absicht: 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

Eine Sache bewusst zu sein - wenn Sie verwenden bundle.putSerializablefür eine Bundleauf eine Meldung hinzugefügt werden, können Sie in das folgende Problem führen:

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

...

Um dies zu umgehen, können Sie Folgendes tun:

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

Welches kann dann so verwendet werden:

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

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

0

Weisen Sie enum auf einfache Weise einen ganzzahligen Wert zu

Siehe folgendes Beispiel:

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

}

Absenderseite:

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

Empfängerseite:

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

Ich denke, Enum in int umzuwandeln (für normale Enum) und dann auf Bundle zu setzen war der einfachste Weg. wie dieser Code für die Absicht:

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

dann für Prüfzustand:

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

aber nicht für alle Aufzählungstypen funktionieren!


0

Ich habe eine Koltin-Erweiterung erstellt:

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

Erstellen Sie ein Bundle und fügen Sie hinzu:

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

und bekomme:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.