Android: Bagaimana cara memasukkan Enum ke dalam Bundel?


332

Bagaimana Anda menambahkan objek Enum ke Bundel Android?


11
Menurut pendapat saya, saran dari staf Google itu buruk. Enum sangat nyaman dan menderita overhead yang dijelaskan layak.
ognian

3
dapatkah Anda melihat kembali jawabannya dan menerima jawaban yang ke-2 jika menurut Anda itu pilihan yang lebih baik.
philipp

6
Di bawah tajuk "Menghindari Enum" di tautan di atas, sekarang tertulis: Mitos Kinerja Versi sebelumnya dari dokumen ini membuat berbagai klaim menyesatkan. Kami membahas beberapa di antaranya di sini.
StackOverflowed

bagian itu bahkan tidak ada lagi.
Nathaniel D. Wagoner

Jawaban:


726

Enum Serializable sehingga tidak ada masalah.

Diberikan enum berikut:

enum YourEnum {
  TYPE1,
  TYPE2
}

Bundel:

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

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

Maksud:

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

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

Apakah ada sesuatu yang salah dengan metode ini: tabungan: outState.putSerializable("trollData", game.getFunkyTrolls());memuat: game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));?
Moberg

21
Saya akan memilih jawaban Anda, tetapi pertanyaannya adalah tentang menambahkan Enum ke Bundel dan balasan Anda menjelaskan bagaimana menambahkannya ke Intent ... Memang hampir sama, tetapi Alejandro di bawah tetap memperbaiki jawaban Anda.
Pooks

2
saat menggunakannya dengan Bundle, ia melemparClassNotFoundException
Tampilan Nama

2
ini bisa sangat lambat dan tidak skala untuk array hal-hal yang mengandung enum, dll. Lihat stackoverflow.com/a/5551155/175156
yincrash

1
@yincrash enum menggunakan serialisasi khusus yang cukup cepat. Bukti: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64

164

Saya tahu ini adalah pertanyaan lama, tetapi saya datang dengan masalah yang sama dan saya ingin berbagi bagaimana saya menyelesaikannya. Kuncinya adalah apa yang dikatakan Miguel: Enum dapat Serializable.

Diberikan enum berikut:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Taruh:

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

3
Berdasarkan ini: stackoverflow.com/questions/15521309/... , custom Enums tidak dapat diserialisasi. Jadi bidang khusus dalam Enum tidak akan diserialisasi. Bagaimana Anda menangani ini?
clu

Pertanyaan bagus @clu! Mungkin kemudian Anda harus berpikir untuk meneruskannya sebagai string seperti yang dinyatakan dalam stackoverflow.com/questions/609860/…
Alejandro Colorado

@clu Dengan tidak mengharapkan bidang khusus akan diserialisasi. Ini berfungsi dengan baik jika itu hanya enum normal seperti pada kode di atas.
bluehallu

@AlejandroColorado apa yang ini tambahkan ke jawaban miguel?
tir38

1
Jawaban Miguel diedit pada 2015. Jawaban asli tidak mengatakan apa pun tentang bundel, hanya menunjukkan contoh niat.
Alejandro Colorado

41

Demi kelengkapan, ini adalah contoh lengkap tentang cara memasukkan dan mendapatkan kembali enum dari bundel.

Diberikan enum berikut:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Anda bisa memasukkan enum ke dalam bundel:

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

Dan dapatkan kembali enum:

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

32

Saya menggunakan kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

kemudian dimasukkan ke dalam Intent:

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

ketika Anda bersih untuk mendapatkan nilai:

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

6
Ini adalah jawaban yang baik, tetapi dapat dilengkapi dengan metode ekstensi, saya menggunakan yang ini di sini: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden

.nameadalah jalan yang sangat penting
Phan Van Linh

Ini tampaknya jauh lebih sederhana daripada mengubah Enum menjadi parcelable, yang akan menciptakan kompleksitas lebih lanjut jika bekerja dengan pustaka basis data Room Android .
Adam Hurwitz

@GabrielDeOliveiraRohden, saya tidak yakin metode ekstensi diperlukan karena tampaknya hanya menghindari penggunaan .namein putString(). Dengan Kotlin itu sudah efisien jika menggunakan .apply. Sebagai contoh :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz

@AdamHurwitz, bukankah fungsi ekstensi yang diusulkan adalah seluruh titik fungsi ekstensi Kotlin? Ini memaksa Anda untuk tidak melakukan kesalahan, itu sempurna! Link @GabrielDeOliveiraRohden bundle.putEnum(key, enum) | bundle.getEnum<>(key)
Yokich

17

Mungkin lebih baik untuk meneruskannya sebagai string dari myEnumValue.name () dan mengembalikannya dari YourEnums.valueOf (s), karena jika tidak, pemesanan enum harus dilestarikan!

Penjelasan yang lebih panjang: Konversi dari tipe enum ordinal ke enum


1
Urutan tidak masalah jika serialisasi-> deserialisasi terjadi segera saat runtime, seperti ketika memanggil dari satu aktivitas ke aktivitas lainnya. Ini bisa menjadi masalah di seluruh proses seperti mengirim Intents dari satu aplikasi ke versi aplikasi yang lebih lama.
miguel

6

Pilihan lain:

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
Anda dapat menggunakan putSerializable(key, value)/ (Type) getSerializable(key)atau putString(key, value.name())/ Type.valueOf(getString(key)), implementasi Parcelable di sini berlebihan dan tidak masuk akal.
Miha_x64

1
Menggunakan Parcelableadalah solusi yang baik untuk menyimpan Arays of Enum-values.
RhodanV5500


2

Untuk Intent Anda dapat menggunakan cara ini:

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

Satu hal yang harus diperhatikan - jika Anda menggunakan bundle.putSerializableuntuk Bundleyang akan ditambahkan ke pemberitahuan, Anda bisa lari ke masalah berikut:

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

...

Untuk menyiasatinya, Anda dapat melakukan hal berikut:

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

Yang kemudian bisa digunakan seperti ini:

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

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

0

Cara sederhana, tetapkan nilai integer ke enum

Lihat contoh berikut:

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

}

Sisi Pengirim:

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

Sisi Penerima:

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

Saya pikir mengkonversi enum ke int (untuk enum normal) dan kemudian mengatur bundel adalah cara termudah. suka kode ini untuk maksud:

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

maka untuk kondisi cek:

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

tetapi tidak bekerja untuk semua tipe enum!


0

Saya telah membuat ekstensi 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) )
}

Buat bundel dan tambahkan:

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

dan dapatkan:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.