안드로이드 : 번들에 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.