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

332

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

zer0stimulus
quelle
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");
Miguel
quelle
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);
Alejandro Colorado
quelle
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");
Das es
quelle
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))
Vladislav
quelle
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

user602359
quelle
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());
    }
}
Charlie Jones
quelle
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

Verwenden Sie bundle.putSerializable (String key, Serializable s) und bundle.getSerializable (String key):

enum Mode = {
  BASIC, ADVANCED
}

Mode m = Mode.BASIC;

bundle.putSerializable("mode", m);

...

Mode m;
m = bundle.getSerializable("mode");

Dokumentation: http://developer.android.com/reference/android/os/Bundle.html

Erwischt
quelle
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?)
}
Rasoul Miri
quelle
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"));
kleine
quelle
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();
m3esma
quelle
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!

c0mmander
quelle
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{}
Moises Portillo
quelle