Android: Enum'u bir pakete nasıl koyabilirim?


332

Bir Android Paketine Enum nesnesini nasıl eklersiniz?


11
Bence Google personelinden tavsiye kötü. Numaralandırmalar çok uygundur ve tarif edilen yükü çekmeye değer.
ognian

3
cevapları tekrar ziyaret edebilir ve daha iyi bir seçim olabileceğini düşünüyorsanız ikincisini kabul edebilir misiniz?
philipp

6
Yukarıdaki bağlantıdaki "Numaralandırmalardan Kaçınmak" başlığı altında şunu söylüyor: Performans Mitleri Bu belgenin önceki sürümlerinde çeşitli yanıltıcı iddialarda bulunulmuştur. Burada bazılarına hitap ediyoruz.
StackOverflowed

bu bölüm artık mevcut değil.
Nathaniel D. Wagoner

Yanıtlar:


726

Numaralandırmalar Serileştirilebilir olduğundan sorun yoktur.

Aşağıdaki numaralandırma göz önüne alındığında:

enum YourEnum {
  TYPE1,
  TYPE2
}

Bundle:

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

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

niyet:

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

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

Bu yöntemle orada bir şeyler yanlış mı: tasarrufu: outState.putSerializable("trollData", game.getFunkyTrolls());yükleme: game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));?
Moberg

21
Cevabınız için oy verirdim, ama soru Enum'u bir Pakete eklemekle ilgiliydi ve cevabınız bunu bir Niyet'e nasıl ekleyeceğinizi açıklıyor ... Verilen hemen hemen aynı şey, ancak Alejandro aşağıda cevabınızı düzeltti.
Pooks

2
Bundle ile kullanırken, atarClassNotFoundException
Görünen Ad

2
bu süper yavaş olabilir ve enum, vb. içeren şeylerin dizilerine ölçeklenmez. Bkz. stackoverflow.com/a/5551155/175156
yincrash

1
@yincrash enum oldukça hızlı özel serileştirme kullanır. İspat: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
Miha_x64

164

Bunun eski bir soru olduğunu biliyorum, ama aynı problemle geldim ve nasıl çözdüğümü paylaşmak istiyorum. Anahtar Miguel'in söylediği şeydir: Enum'lar Serializable.

Aşağıdaki numaralandırma göz önüne alındığında:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Koymak:

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

3
Buna dayanarak: stackoverflow.com/questions/15521309/… , özel Numaralandırmalar serileştirilemez. Bu nedenle, bir Enum'daki özel alanlar serileştirilmez. Nasıl anlaştın onunla birlikte?
clu

Güzel soru @clu! Belki o zaman onu stackoverflow.com/questions/609860/…
Alejandro Colorado '

@clu Özel alanların serileştirilmesini beklemeyerek. Yukarıdaki kodda olduğu gibi normal bir numaralandırma ise iyi çalışır.
bluehallu

@AlejandroColorado bu miguel'in cevabına ne katıyor?
tir38

1
Miguel'in cevabı 2015'te düzenlendi. Orijinal cevap demetler hakkında hiçbir şey söylemedi, sadece bir niyet örneği gösterdi.
Alejandro Colorado

41

Tamlık uğruna, bu bir demetten bir enumun nasıl takılacağı ve geri alınacağının tam bir örneğidir.

Aşağıdaki numaralandırma göz önüne alındığında:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Numaralandırmayı bir pakete koyabilirsiniz:

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

Numaralandırmayı geri alın:

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

32

Kotlin kullanıyorum.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

sonra Niyet koymak:

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

değer elde etmek için net olduğunuzda:

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

6
Bu iyi bir cevap, ama bir uzatma yöntemi ile tamamlanabilir, ben burada bunu kullanın: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden

.nameönemli bir yoldur
Phan Van Linh

Bu dönüm çok daha basit görünüyor Enum Android'in ile çalışan takdirde daha fazla karmaşıklık yaratacak bir parcelable, içine Odası veritabanı kütüphanesine.
Adam Hurwitz

@GabrielDeOliveiraRohden, sadece .namein kullanmaktan kaçındığı için uzantı yönteminin gerekli olduğundan emin değilim putString(). Kotlin ile zaten kullanılırsa aerodinamik .apply. Örneğin :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz

@AdamHurwitz, önerilen genişletme işlevi Kotlins genişletme işlevlerinin tüm noktası değil mi? Hata yapmamanıza zorlar, mükemmel! @GabrielDeOliveiraRohden bağlantısı bundle.putEnum(key, enum) | bundle.getEnum<>(key)
Yokich

17

MyEnumValue.name () öğesinden dize olarak geçirmek ve YourEnums.valueOf (s) öğesinden geri yüklemek daha iyi olabilir, aksi halde numaralandırmanın sırası korunmalıdır!

Daha uzun açıklama: Enum ordinalinden enum tipine dönüştür


1
Serileştirme-> serileştirme işleminin derhal çalışma zamanında gerçekleşip gerçekleşmediği, örneğin bir aktiviteden diğerine çağrı yaparken sıralama önemli değildir. Amaçları bir uygulamadan uygulamanın eski sürümlerine göndermek gibi işlemler arasında bir sorun olabilir.
miguel

6

Başka seçenek:

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
Ya kullanımı can putSerializable(key, value)/ (Type) getSerializable(key)veya putString(key, value.name())/ Type.valueOf(getString(key)), burada Parcelable uygulama gereksiz ve saçmadır.
Miha_x64

1
ParcelableEnum-değerleri Dizilerini saklamak için kullanmak iyi bir çözümdür.
RhodanV5500


2

İçin Niyet Bu şekilde kullanabilirsiniz:

Amaç: 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

Dikkat edilmesi gereken bir şey var - bir bildirime eklenecek bundle.putSerializablebir Bundleiçin kullanıyorsanız , aşağıdaki sorunla karşılaşabilirsiniz:

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

...

Bu sorunu çözmek için aşağıdakileri yapabilirsiniz:

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

Hangisi daha sonra şu şekilde kullanılabilir:

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

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

0

Basit bir yol, numaralandırma için tamsayı değeri atayın

Aşağıdaki örneğe bakın:

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

}

Gönderen Tarafı:

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

Alıcı tarafı:

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

Ben enum int dönüştürmek düşünüyorum (normal enum için) ve daha sonra paket set kolay yolu oldu. niyet için bu kod gibi:

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

ardından kontrol durumu için:

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

ancak tüm numaralandırma türlerinde çalışmaz!


0

Bir Koltin uzantısı oluşturdum:

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

Bir paket oluşturun ve ekleyin:

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

ve Al:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.