天天看點

enum類型序列化Serializable和Parcelableenum類型被intent所攜帶時需要注意的地方

enum類型被intent所攜帶時需要注意的地方

https://blog.csdn.net/tedzyc/article/details/8373399

2012年12月22日 17:18:30 tedzyc 閱讀數:13847

        一般我們在Activity之間傳遞對象時多用Parcelable。比如寫一個class,在這個class上标明implements Parcelable并實作接口就可以用Intent.putExtra(String, Parcelable)了。對于傳遞enum對象,假設也采用此方法,即像http://stackoverflow.com/questions/2836256/passing-enum-or-object-through-an-intent-the-best-solution裡面3樓說的:

  1. public enum MyEnum implements Parcelable {

  2. VALUE;

  3. @Override

  4. public int describeContents() {

  5. return 0;

  6. }

  7. @Override

  8. public void writeToParcel(final Parcel dest, final int flags) {

  9. dest.writeInt(ordinal());

  10. }

  11. public static final Creator<MyEnum> CREATOR = new Creator<MyEnum>() {

  12. @Override

  13. public MyEnum createFromParcel(final Parcel source) {

  14. return MyEnum.values()[source.readInt()];

  15. }

  16. @Override

  17. public MyEnum[] newArray(final int size) {

  18. return new MyEnum[size];

  19. }

  20. };

  21. }

  22. You can than use Intent.putExtra(String, Parcelable).

        那麼我們先定義一個MyEnum變量a,再調用intent.putExtra("name", a),會報The method putExtra(String, Parcelable) is ambiguous for the type Intent的錯,為何?

因為enum自身實作了Serializable接口,Enum類的源代碼裡這麼寫的:

  1. public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> {

  2. ... ...

  3. }

        之後你的MyEnum類再實作Parcelable接口,而intent裡面有這樣兩個函數:Intent.putExtra(String, Parcelable)和Intent.putExtra(String, Serializable),你的MyEnum類實作了Serializable和Parcelable兩個接口,在調用Intent.putExtra時,編譯器就不知道該選Intent.putExtra(String, Parcelable)還是Intent.putExtra(String, Serializable),導緻二義性。那麼上面的說法是否真的無用?  其實這種寫法在MyEnum對象作為類Father1的成員時還是可以這麼寫的,我們在Activity間傳Father1,Father1是可以實作Parcelable接口的。Father1内部處理MyEnum成員時可以這樣:

  1. private Father1(Parcel in) {

  2. mField = in.readInt();

  3. mMyEnum = MyEnum.CREATOR.createFromParcel(in);

  4. }

  5. public void writeToParcel(Parcel dest, int flags) {

  6. dest.writeInt(mField);

  7. mMyEnum.writeToParcel(dest, flags);

  8. }

        經測試,也可以把enum傳遞出去。

        既然上述MyEnum的寫法可以适應enum作為Parcelable類成員來傳遞,而不能作為單獨的對象來傳遞,要兼得二者該如何做?

        首先,MyEnum不需實作Parcelable接口,單獨傳遞MyEnum對象時就用Intent.putExtra(String, Serializable)。

        然後把MyEnum的createFromParcel()和writeToParcel()的代碼整合進Father類,代碼片段(變量名有改動):

  1. private Father2(Parcel in) {

  2. mField = in.readInt();

  3. mAnotherEnum = AnotherEnum.values()[in.readInt()];

  4. }

  5. public static final Parcelable.Creator<Father2> CREATOR = new Parcelable.Creator<Father2>() {

  6. public Father2 createFromParcel(Parcel in) {

  7. return new Father2(in);

  8. }

  9. @Override

  10. public Father2[] newArray(int size) {

  11. return new Father2[size];

  12. }

  13. };

  14. @Override

  15. public void writeToParcel(Parcel dest, int flags) {

  16. dest.writeInt(mField);

  17. dest.writeInt(mAnotherEnum.ordinal());

  18. }

        再用Intent.putExtra(String, Parcelable)來傳Father2對象就可以了。

        再談一下Enum類的values()方法,這個方法是無法通過eclipse檢視到的,它的定義在這裡,它傳回所有的定義過的枚舉值,enum的底層實作就是定義從0到N的數個整數,隻不過為每個整數取了個别名,一個enum變量就是這數個整數之一,這個enum變量的ordinal()方法就是傳回其在這數個整數中的位置。values()靜态方法傳回一個包含這數個整數的數組。

給出示例代碼(免積分下載下傳),在MainActivity.java三處注釋的地方,分别解注釋再運作,就會認識得比較清楚了。