Android: Làm cách nào để đặt Enum trong Gói?


332

Làm thế nào để bạn thêm một đối tượng Enum vào Gói Android?


11
Theo tôi rằng lời khuyên từ nhân viên Google là xấu. Enums là rất thuận tiện và chịu đựng chi phí được mô tả là có giá trị.
thức

3
bạn có thể xem lại câu trả lời và chấp nhận câu trả lời thứ 2 nếu bạn nghĩ nó có thể là lựa chọn tốt hơn.
philipp

6
Trong tiêu đề "Tránh Enums" trong liên kết ở trên, bây giờ nó nói điều này: Huyền thoại hiệu suất Các phiên bản trước của tài liệu này đã đưa ra các tuyên bố sai lệch khác nhau. Chúng tôi giải quyết một số trong số họ ở đây.
StackOverflow

phần đó thậm chí không còn hiện diện nữa.
Nathaniel D. Wagoner

Câu trả lời:


726

Enums là serializable nên không có vấn đề.

Cho enum sau:

enum YourEnum {
  TYPE1,
  TYPE2
}

Gói:

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

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

Ý định:

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

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

Có điều gì đó sai với phương pháp này: tiết kiệm: outState.putSerializable("trollData", game.getFunkyTrolls());đang tải : game.setFunkyTrolls((Game.FunkyTroll[]) savedInstanceState.getSerializable("trollData"));?
Moberg

21
Tôi đã bỏ phiếu cho câu trả lời của bạn, nhưng câu hỏi là về việc thêm Enum vào Gói và câu trả lời của bạn giải thích cách thêm nó vào Ý định ... Được cho là gần như tương tự, nhưng Alejandro bên dưới đã sửa câu trả lời của bạn.
Pooks

2
khi sử dụng nó với Bundle, nó sẽ némClassNotFoundException
Tên hiển thị

2
điều này có thể siêu chậm và không mở rộng thành mảng của những thứ có chứa enum, v.v. Xem stackoverflow.com/a/5551155/175156
yincrash

1
@yincrash enum sử dụng tuần tự hóa tùy chỉnh khá nhanh. Bằng chứng: docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/ mẹo
Miha_x64

164

Tôi biết đây là một câu hỏi cũ, nhưng tôi đã gặp vấn đề tương tự và tôi muốn chia sẻ cách tôi giải quyết nó. Điều quan trọng là những gì Miguel nói: Enums là serializable.

Cho enum sau:

enum YourEnumType {
    ENUM_KEY_1, 
    ENUM_KEY_2
}

Đặt:

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

3
Dựa trên điều này: stackoverflow.com/questions/15521309/ , các Enums tùy chỉnh không được tuần tự hóa. Vì vậy, các trường tùy chỉnh trong Enum sẽ không được nối tiếp. Làm thế nào để bạn đối phó với điều này?
clu

Câu hỏi hay đấy @clu! Có lẽ sau đó bạn nên nghĩ đến việc chuyển nó thành một chuỗi như đã nêu trong stackoverflow.com/questions/609860/ mẹo
Alejandro Colorado

@clu Bởi không mong đợi các trường tùy chỉnh sẽ được tuần tự hóa. Nó hoạt động tốt nếu nó chỉ là một enum bình thường như trong đoạn mã trên.
bluehallu

@AlejandroColorado điều này thêm gì vào câu trả lời của Miguel?
tir38

1
Câu trả lời của Miguel đã được chỉnh sửa vào năm 2015. Câu trả lời ban đầu không nói gì về các gói, nó chỉ cho thấy một ví dụ về ý định.
Alejandro Colorado

41

Để hoàn thiện hơn, đây là một ví dụ đầy đủ về cách đưa vào và lấy lại một enum từ một gói.

Cho enum sau:

enum EnumType{
    ENUM_VALUE_1,
    ENUM_VALUE_2
}

Bạn có thể đặt enum vào một gói:

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

Và lấy lại enum:

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

32

Tôi sử dụng kotlin.

companion object {

        enum class Mode {
            MODE_REFERENCE,
            MODE_DOWNLOAD
        }
}

sau đó đưa vào Ý định:

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

khi bạn nhận được giá trị:

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

6
Đây là một câu trả lời hay, nhưng nó có thể được bổ sung bằng một phương pháp mở rộng, tôi sử dụng phương pháp này ở đây: gist.github.com/Grohden/eea5ff9d5e3ba955aa2f57ff0df2683f
Gabriel De Oliveira Rohden 23/8/18

.namelà con đường rất quan trọng
Phan Văn Linh

Điều này có vẻ đơn giản hơn nhiều so với việc biến Enum thành một bưu kiện, điều này sẽ tạo ra sự phức tạp hơn nữa nếu làm việc với thư viện cơ sở dữ liệu Room của Android .
Adam Hurwitz

@GabrielDeOliveiraRohden, tôi không chắc phương thức mở rộng là cần thiết vì dường như chỉ tránh sử dụng phần .nametrong putString(). Với Kotlin, nó đã được sắp xếp hợp lý nếu sử dụng .apply. Ví dụ :ContentFragment.newInstance(Bundle().apply { putString(FEED_TYPE_KEY, SAVED.name) })
Adam Hurwitz

@AdamHurwitz, không phải chức năng mở rộng được đề xuất là toàn bộ điểm của các chức năng mở rộng của Kotlins sao? Nó buộc bạn không phạm sai lầm, thật hoàn hảo! Liên kết của bundle.putEnum(key, enum) | bundle.getEnum<>(key)
@GabrielDeOliveiraRohden

17

Có thể tốt hơn để chuyển nó dưới dạng chuỗi từ myEnumValue.name () và khôi phục nó từ YourEnums.valueOf (s), vì nếu không thì lệnh của enum phải được giữ nguyên!

Giải thích dài hơn: Chuyển đổi từ enum ordinal sang enum type


1
Việc đặt hàng không thành vấn đề nếu việc tuần tự hóa-> khử lưu huỳnh xảy ra ngay lập tức trong thời gian chạy, chẳng hạn như khi gọi từ hoạt động này sang hoạt động khác. Nó có thể là một vấn đề trên các quy trình như gửi Ý định từ một ứng dụng đến các phiên bản cũ hơn của ứng dụng.
miguel

6

Một lựa chọn khác:

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
Bạn có thể sử dụng putSerializable(key, value)/ (Type) getSerializable(key)hoặc putString(key, value.name())/ Type.valueOf(getString(key)), triển khai Parcelable ở đây là dự phòng và vô nghĩa.
Miha_x64

1
Sử dụng Parcelablelà một giải pháp tốt để lưu trữ Mảng giá trị Enum.
RhodanV5500


2

Đối với ý định, bạn có thể sử dụng cách này:

Ý định: kotlin

Hoạt động đầu tiên:

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

Hoạt động thứ hai:

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

1

Một điều cần phải nhận thức được - nếu bạn đang sử dụng bundle.putSerializablecho một Bundleđể được thêm vào một thông báo, bạn có thể chạy vào các vấn đề sau đây:

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

...

Để giải quyết vấn đề này, bạn có thể làm như sau:

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

Mà sau đó có thể được sử dụng như vậy:

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

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

0

Một cách đơn giản, gán giá trị nguyên cho enum

Xem ví dụ sau:

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

}

Phía người gửi:

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

Bên nhận:

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

Tôi nghĩ chuyển đổi enum thành int (đối với enum bình thường) và sau đó thiết lập gói là cách dễ nhất. thích mã này cho ý định:

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

sau đó cho trạng thái kiểm tra:

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

nhưng không làm việc cho tất cả các loại enum!


0

Tôi đã tạo tiện ích mở rộng 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) )
}

Tạo một gói và thêm:

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

và lấy:

intent?.getEnumExtra< ENUM_CLAS >( "KEY" )?.let{}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.