Android: jak umieścić Enum w pakiecie?

332

Jak dodać obiekt Enum do pakietu Androida?

zer0stimulus
źródło
11
Moim zdaniem porady pracowników Google są złe. Wytryski są bardzo wygodne i cierpi opisany narzut jest wortowany.
ognian
3
czy możesz ponownie przeczytać odpowiedzi i zaakceptować drugą, jeśli uważasz, że może to być lepszy wybór.
philipp
6
Pod nagłówkiem „Unikanie wyliczeń” w powyższym linku jest teraz napisane: Mity o wydajności Poprzednie wersje tego dokumentu zawierały różne mylące twierdzenia. Zajmujemy się niektórymi z nich tutaj.
StackOverflowed
ta sekcja nie jest już nawet obecna.
Nathaniel D. Wagoner

Odpowiedzi:

726

Wyliczenia są serializowane, więc nie ma problemu.

Biorąc pod uwagę następujący wyliczenie:

enum YourEnum {
  TYPE1,
  TYPE2
}

Pakiet:

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

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

Zamiar:

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

// get
yourEnum = (YourEnum) intent.getSerializableExtra("key");
miguel
źródło
Czy coś jest nie tak z tą metodą: zapisywanie: outState.putSerializable("trollData", game.getFunkyTrolls());ładowanie game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));:?
Moberg
21
Głosowałbym na twoją odpowiedź, ale pytanie dotyczyło dodania Enum do pakietu, a twoja odpowiedź wyjaśnia, jak dodać go do zamiaru ... Przyznaję, że to prawie to samo, ale Alejandro poniżej naprawił twoją odpowiedź.
Pooks,
2
gdy używa go z pakietem, rzucaClassNotFoundException
Nazwa wyświetlana
2
może to być bardzo wolne i nie skaluje się do tablic rzeczy, które zawierają wyliczenia itp. Zobacz stackoverflow.com/a/5551155/175156
yincrash
1
@yincrash enum używa niestandardowej serializacji, która jest dość szybka. Dowód: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64
164

Wiem, że to stare pytanie, ale napotkałem ten sam problem i chciałbym podzielić się tym, jak to rozwiązałem. Kluczem jest to, co powiedział Miguel: Enumy można nadać szeregowo.

Biorąc pod uwagę następujący wyliczenie:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Położyć:

Bundle args = new Bundle();
args.putSerializable("arg", YourEnumType.ENUM_KEY_1);
Alejandro Colorado
źródło
3
W oparciu o to: stackoverflow.com/questions/15521309 /... niestandardowe wyliczenia nie są serializowane. Tak więc niestandardowe pola w Enum nie będą serializowane. Jak sobie z tym radzisz?
clu
Ładne pytanie @clu! Może wtedy powinieneś pomyśleć, przekazując go jako ciąg znaków, jak podano w stackoverflow.com/questions/609860/...
Alejandro Colorado
@clu Nie oczekując serializacji niestandardowych pól. Działa dobrze, jeśli jest to zwykłe wyliczenie, jak w powyższym kodzie.
bluehallu
@AlejandroColorado co to dodaje do odpowiedzi Miguela?
tir38
1
Odpowiedź Miguela została zredagowana w 2015 roku. Oryginalna odpowiedź nic nie mówiła o pakietach, pokazała jedynie przykład zamiaru.
Alejandro Colorado,
41

Dla kompletności jest to pełny przykład tego, jak umieścić i odzyskać wyliczenie z pakietu.

Biorąc pod uwagę następujący wyliczenie:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Możesz umieścić wyliczenie w pakiecie:

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

I odzyskaj wyliczenie:

EnumType enumType = (EnumType)bundle.getSerializable("enum_key");
TheIT
źródło
32

Używam kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

następnie wprowadź Intent:

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

kiedy zarabiasz, aby uzyskać wartość:

mode = Mode.valueOf(intent.getStringExtra(KEY_MODE))
Vladislav
źródło
6
To dobra odpowiedź, ale można ją uzupełnić metodą rozszerzenia, używam tego tutaj: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden
.namejest bardzo ważną ścieżką
Phan Van Linh
Wydaje się to o wiele prostsze niż przekształcenie Enum w paczkowany, co spowodowałoby większą złożoność, gdyby pracowała z biblioteką baz danych Room w Androidzie .
Adam Hurwitz
@GabrielDeOliveiraRohden, nie jestem pewien, potrzebna jest metoda rozszerzenie, jak się wydaje wyłącznie do użytku unikaj z .namew putString(). Z Kotlin jest już usprawniony, jeśli używasz .apply. Na przykład :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz
@AdamHurwitz, czy proponowana funkcja rozszerzenia nie jest całym punktem funkcji rozszerzenia Kotlin? Zmusza cię do nie popełniania błędów, jest idealny! Link bundle.putEnum(key, enum) | bundle.getEnum<>(key)
@GabrielDeOliveiraRohden
17

Może być lepiej przekazać go jako ciąg z myEnumValue.name () i przywrócić go z YourEnums.valueOf (s), ponieważ w przeciwnym razie kolejność wyliczenia musi zostać zachowana!

Dłuższe objaśnienie: Konwertuj z enum ordinal na enum

użytkownik602359
źródło
1
Kolejność nie ma znaczenia, czy serializacja-> deserializacja odbywa się natychmiast w czasie wykonywania, na przykład podczas wywoływania z jednego działania do drugiego. Może to stanowić problem w wielu procesach, takich jak wysyłanie Intencji z jednej aplikacji do starszych wersji aplikacji.
Miguel
6

Inna opcja:

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
źródło
1
Możesz użyć opcji putSerializable(key, value)/ (Type) getSerializable(key)lub putString(key, value.name())/ Type.valueOf(getString(key)), implementacja działki jest tutaj zbędna i bezsensowna.
Miha_x64,
1
Korzystanie Parcelablejest dobrym rozwiązaniem do przechowywania tablic wartości Enum.
RhodanV5500
2

W przypadku programu Intent możesz użyć tego sposobu:

Przeznaczenie: 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
źródło
1

Jedną rzeczą, aby mieć świadomość - jeśli używasz bundle.putSerializabledla Bundlezostać dodane do zawiadomienia, można uruchomić w następującej kwestii:

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

...

Aby obejść ten problem, możesz wykonać następujące czynności:

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

Które można następnie wykorzystać w następujący sposób:

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

// Get 
MyEnum myEnum = MyEnum.fromCode(bundle.getInt("key"));
Drobnica
źródło
0

W prosty sposób przypisz wartość całkowitą do wyliczenia

Zobacz następujący przykład:

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

}

Strona nadawcy:

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

Strona odbiornika:

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
źródło
0

Myślę, że konwersja enum na int (dla normalnego enum), a następnie ustawienie pakietu było najłatwiejszym sposobem. jak ten kod dla zamiaru:

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

następnie dla stanu kontroli:

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

ale nie działa dla wszystkich typów enum!

c0mmander
źródło
0

Utworzyłem rozszerzenie 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) )
}

Utwórz pakiet i dodaj:

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

i dostać:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Moises Portillo
źródło