안드로이드 : 번들에 Enum을 넣는 방법?


332

Android 번들에 Enum 객체를 어떻게 추가합니까?


11
내 의견으로는 Google 직원의 조언이 나쁘다는 것입니다. 열거 형은 매우 편리하고 설명 된 오버 헤드가 가치가 있습니다.
— ognian

3
더 나은 선택이라고 생각되면 답변을 다시 방문하고 두 번째 답변을 수락 할 수 있습니까?
— philipp

6
위의 링크에서 "Avoiding Enums"라는 제목 아래에 다음과 같이 표시됩니다. Performance Myths이 문서의 이전 버전에서는 여러 가지 잘못된 주장을했습니다. 우리는 여기에 그 중 일부를 다룹니다.
— StackOverflowed

그 섹션은 더 이상 존재하지 않습니다.
— Nathaniel D. Wagoner 2018 년

답변:


726

열거 형은 직렬화 가능하므로 문제가 없습니다.

다음 열거가 주어지면 :

enum YourEnum {
  TYPE1,
  TYPE2
}

묶음:

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

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

의지:

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

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

이 방법에 문제가 있습니까? saving : outState.putSerializable("trollData", game.getFunkyTrolls());loading : game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));?
— Moberg

21
귀하의 답변에 투표를 하였지만 Enum을 번들에 추가하는 것에 관한 질문이 있었고 귀하의 답변에 인 텐트에 추가하는 방법이 설명되어 있습니다 ... 거의 같은 것이지만 아래 Alejandro는 귀하의 답변을 수정했습니다.
— Pooks

2
번들과 함께 사용하면 던집니다ClassNotFoundException
— 표시 이름

2
이것은 매우 느릴 수 있으며 열거 형 등을 포함하는 배열로 확장되지 않습니다. stackoverflow.com/a/5551155/175156
— yincrash

1
@yincrash enum은 매우 빠른 사용자 정의 직렬화를 사용합니다. 증명 : docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/…
— Miha_x64

164

나는 이것이 오래된 질문이라는 것을 알고 있지만 같은 문제가 발생하여 어떻게 해결했는지 공유하고 싶습니다. 핵심은 Miguel이 말한 것입니다. 열거 형은 직렬화 가능합니다.

다음 열거가 주어지면 :

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

놓다:

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

3
이를 기반으로 stackoverflow.com/questions/15521309/… , 사용자 정의 열거 형은 직렬화 할 수 없습니다. 따라서 Enum의 사용자 정의 필드는 직렬화되지 않습니다. 이것을 어떻게 처리합니까?
— clu

좋은 질문 @clu! 아마도 그렇다면 당신은 그것을 stackoverflow.com/questions/609860/…에
— Alejandro Colorado

@clu 사용자 정의 필드가 직렬화 될 것으로 예상하지 않음. 위의 코드와 같이 정상적인 열거 형이면 정상적으로 작동합니다.
— bluehallu

@AlejandroColorado 이것이 Miguel의 답변에 추가하는 것은 무엇입니까?
— tir38

1
Miguel의 답변은 2015 년에 수정되었습니다. 원래 답변은 번들에 대해서는 아무 것도 말하지 않았으며 의도의 예일뿐입니다.
— 알레한드로 콜로라도

41

완전성을 위해 이것은 번들에서 열거 형을 넣고 다시 얻는 방법의 전체 예입니다.

다음 열거가 주어지면 :

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

열거 형을 번들에 넣을 수 있습니다.

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

그리고 열거 형을 다시 얻으십시오.

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

32

나는 kotlin을 사용합니다.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

그런 다음 의도에 넣습니다.

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

당신이 가치를 얻기 위해 그물 때 :

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

6
이것은 좋은 대답이지만 확장 방법으로 보완 할 수 있습니다. 여기에서 이것을 사용하십시오 : gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
— Gabriel De Oliveira Rohden

.name매우 중요한 경로는
— 판 반 린

이것은 Enum 을 소포로 바꾸는 것보다 훨씬 간단 해 보입니다 .Android의 Room 데이터베이스 라이브러리로 작업하는 경우 더 복잡해집니다 .
— Adam Hurwitz

@GabrielDeOliveiraRohden, .namein의 사용을 피하는 것처럼 확장 방법이 필요한지 확실하지 않습니다 putString(). Kotlin에서는을 사용하면 이미 간소화되었습니다 .apply. 예 :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
— Adam Hurwitz

@AdamHurwitz, 제안 된 확장 기능이 Kotlins 확장 기능의 전체 요점이 아닌가? 실수하지 않도록 강요합니다. 완벽합니다! @GabrielDeOliveiraRohden의 링크 bundle.putEnum(key, enum) | bundle.getEnum<>(key)
— Yokich

17

myEnumValue.name ()에서 문자열로 전달하고 YourEnums.valueOf (s)에서 복원하는 것이 좋습니다. 그렇지 않으면 열거의 순서가 유지되어야합니다!

더 긴 설명 : 열거 형 서수에서 열거 형으로 변환


1
순서화는 직렬화-> 직렬화 해제가 한 활동에서 다른 활동으로 호출 할 때와 같이 런타임에 즉시 발생하는 경우 중요하지 않습니다. 하나의 앱에서 인 텐트를 이전 버전의 앱으로 보내는 것과 같은 프로세스에서 문제가 될 수 있습니다.
— miguel

6

다른 옵션 :

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
putSerializable(key, value)/ (Type) getSerializable(key)또는 putString(key, value.name())/ 를 사용할 수 있습니다 Type.valueOf(getString(key)). 여기에서 Parcelable 구현은 중복적이고 무의미합니다.
— Miha_x64

1
사용 Parcelable은 열거 형 값의 배열을 저장하는 좋은 솔루션입니다.
— RhodanV5500


2

들어 의향 이 방법을 사용할 수 있습니다 :

의도 : 코 틀린

FirstActivity :

val intent = Intent(context, SecondActivity::class.java)
intent.putExtra("type", typeEnum.A)
startActivity(intent)

두 번째 활동 :

override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState) 
     //...
     val type = (intent.extras?.get("type") as? typeEnum.Type?)
}

1

한 가지 알아야 할 - 당신이 사용하는 경우 bundle.putSerializableA는 대한 Bundle통지에 추가하려면 다음 문제로 실행할 수 있습니다 :

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

...

이 문제를 해결하려면 다음을 수행하십시오.

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

다음과 같이 사용할 수 있습니다.

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

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

0

간단한 방법으로 정수 값을 열거 형에 할당하십시오.

다음 예를 참조하십시오.

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

}

발신자 측 :

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

수신기 측 :

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

enum을 int로 변환하고 (일반 enum의 경우) 번들로 설정하는 것이 가장 쉬운 방법이라고 생각합니다. 의도적 으로이 코드와 같이 :

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

그런 다음 확인 상태 :

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

그러나 모든 열거 형 유형에는 작동하지 않습니다!


0

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

번들을 작성하고 추가하십시오.

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

그리고 얻다:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.