Android: Comment mettre un Enum dans un Bundle?

332

Comment ajouter un objet Enum à un bundle Android?

zer0stimulus
la source
11
À mon avis, les conseils du personnel de Google sont mauvais. Les énumérations sont très pratiques et la souffrance des frais généraux décrits en vaut la peine.
ognian
3
pouvez-vous revoir les réponses et accepter la 2e si vous pensez que cela pourrait être un meilleur choix.
philipp
6
Sous l'intitulé «Éviter les énumérations» dans le lien ci-dessus, il est maintenant dit ceci: Mythes sur les performances Les versions précédentes de ce document faisaient diverses allégations trompeuses. Nous en abordons certains ici.
StackOverflowed
cette section n'est même plus présente.
Nathaniel D. Waggoner

Réponses:

726

Les énumérations sont sérialisables, il n'y a donc aucun problème.

Étant donné l'énumération suivante:

enum YourEnum {
  TYPE1,
  TYPE2
}

Paquet:

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

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

Intention:

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

// get
yourEnum = (YourEnum) intent.getSerializableExtra("key");
miguel
la source
Y a-t-il un problème avec cette méthode: sauvegarde: outState.putSerializable("trollData", game.getFunkyTrolls());chargement game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));:?
Moberg
21
J'aurais voté pour votre réponse, mais la question concernait l'ajout de l'énumération à un ensemble et votre réponse explique comment l'ajouter à une intention ... Certes, c'est presque la même chose, mais Alejandro ci-dessous a corrigé votre réponse.
Pooks
2
lors de son utilisation avec Bundle, il lanceClassNotFoundException
Nom d'affichage
2
cela peut être super lent et ne s'adapte pas aux tableaux de choses qui contiennent de l'énumération, etc. Voir stackoverflow.com/a/5551155/175156
yincrash
1
@yincrash enum utilise une sérialisation personnalisée qui est assez rapide. Preuve: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64
164

Je sais que c'est une vieille question, mais je suis venu avec le même problème et je voudrais partager comment je l'ai résolu. La clé est ce que Miguel a dit: les énumérations sont sérialisables.

Étant donné l'énumération suivante:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Mettre:

Bundle args = new Bundle();
args.putSerializable("arg", YourEnumType.ENUM_KEY_1);
Alejandro Colorado
la source
3
Sur la base de ceci: stackoverflow.com/questions/15521309/… , les énumérations personnalisées ne sont pas sérialisables. Les champs personnalisés d'un Enum ne seront donc pas sérialisés. Comment gérez-vous cela?
clu
Jolie question @clu! Peut-être que vous devriez alors penser en le passant comme une chaîne comme indiqué dans stackoverflow.com/questions/609860/…
Alejandro Colorado
@clu En ne s'attendant pas à ce que les champs personnalisés soient sérialisés. Cela fonctionne bien si c'est juste une énumération normale comme dans le code ci-dessus.
bluehallu
@AlejandroColorado qu'est-ce que cela ajoute à la réponse de miguel?
tir38
1
La réponse de Miguel a été révisée en 2015. La réponse originale ne disait rien sur les paquets, elle ne montrait qu'un exemple d'intention.
Alejandro Colorado
41

Par souci d'exhaustivité, ceci est un exemple complet de la façon de mettre en place et de récupérer une énumération à partir d'un bundle.

Étant donné l'énumération suivante:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Vous pouvez mettre l'énumération dans un bundle:

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

Et récupérez l'énumération:

EnumType enumType = (EnumType)bundle.getSerializable("enum_key");
TheIT
la source
32

J'utilise du kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

puis mettre en intention:

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

lorsque vous net pour obtenir de la valeur:

mode = Mode.valueOf(intent.getStringExtra(KEY_MODE))
Vladislav
la source
6
C'est une bonne réponse, mais elle peut être complétée par une méthode d'extension, j'utilise celle-ci ici: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden
.nameest un chemin très important
Phan Van Linh
Cela semble beaucoup plus simple que de transformer l' Enum en une parcellaire, ce qui créerait une complexité supplémentaire si vous travaillez avec la bibliothèque de base de données Room d'Android .
Adam Hurwitz
@GabrielDeOliveiraRohden, je ne suis pas sûr que la méthode d'extension soit nécessaire car elle semble éviter uniquement l'utilisation de .namein putString(). Avec Kotlin, c'est déjà simplifié si vous l'utilisez .apply. Par exemple :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz
@AdamHurwitz, la fonction d'extension proposée n'est-elle pas l'intégralité des fonctions d'extension de Kotlins? Cela vous oblige à ne pas faire d'erreurs, c'est parfait! Lien de bundle.putEnum(key, enum) | bundle.getEnum<>(key)
@GabrielDeOliveiraRohden
17

Il peut être préférable de le passer en tant que chaîne à partir de myEnumValue.name () et de le restaurer à partir de YourEnums.valueOf (s), sinon la commande de l'énumération doit être préservée!

Explication plus longue: conversion de l'énumération ordinale en type énumération

user602359
la source
1
L'ordre n'a pas d'importance si la sérialisation-> désérialisation se produit immédiatement au moment de l'exécution, comme lors d'un appel d'une activité à une autre. Cela pourrait être un problème dans tous les processus tels que l'envoi d'intentions d'une application à une ancienne version de l'application.
miguel
6

Une autre 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
la source
1
Vous pouvez utiliser putSerializable(key, value)/ (Type) getSerializable(key)ou putString(key, value.name())/ Type.valueOf(getString(key)), la mise en œuvre de Parcelable est ici redondante et absurde.
Miha_x64
1
L'utilisation Parcelableest une bonne solution pour stocker des tableaux de valeurs Enum.
RhodanV5500
2

Pour l' intention, vous pouvez utiliser cette méthode:

Intention: 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
la source
1

Une chose à savoir - si vous utilisez bundle.putSerializablepour Bundleajouter un à une notification, vous pouvez rencontrer le problème suivant:

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

...

Pour contourner ce problème, vous pouvez procéder comme suit:

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

Qui peut ensuite être utilisé comme ceci:

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

// Get 
MyEnum myEnum = MyEnum.fromCode(bundle.getInt("key"));
Smalls
la source
0

Une manière simple, attribuer une valeur entière à enum

Voir l'exemple suivant:

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

}

Côté expéditeur:

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

Côté récepteur:

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
la source
0

Je pense que convertir l'énumération en int (pour l'énumération normale), puis définir le bundle a été la manière la plus simple. comme ce code d'intention:

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

puis pour vérifier l'état:

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

mais ne fonctionne pas pour tous les types d'énumération!

c0mmander
la source
0

J'ai créé une extension 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) )
}

Créez un bundle et ajoutez:

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

et obtenir:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Moises Portillo
la source