enum类型序列化Serializable和Parcelable

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.  
  4. @Override

  5. public int describeContents() {

  6. return 0;

  7. }

  8.  
  9. @Override

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

  11. dest.writeInt(ordinal());

  12. }

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

  15. @Override

  16. public MyEnum createFromParcel(final Parcel source) {

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

  18. }

  19.  
  20. @Override

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

  22. return new MyEnum[size];

  23. }

  24. };

  25. }

  26.  
  27. 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.  
  6. public void writeToParcel(Parcel dest, int flags) {

  7. dest.writeInt(mField);

  8. mMyEnum.writeToParcel(dest, flags);

  9. }

 

        经测试,也可以把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.  
  6. public static final Parcelable.Creator<Father2> CREATOR = new Parcelable.Creator<Father2>() {

  7.  
  8. public Father2 createFromParcel(Parcel in) {

  9. return new Father2(in);

  10. }

  11.  
  12. @Override

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

  14. return new Father2[size];

  15. }

  16.  
  17. };

  18.  
  19. @Override

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

  21. dest.writeInt(mField);

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

  23. }

        再用Intent.putExtra(String, Parcelable)来传Father2对象就可以了。

 

        再谈一下Enum类的values()方法,这个方法是无法通过eclipse查看到的,它的定义在这里,它返回所有的定义过的枚举值,enum的底层实现就是定义从0到N的数个整数,只不过为每个整数取了个别名,一个enum变量就是这数个整数之一,这个enum变量的ordinal()方法就是返回其在这数个整数中的位置。values()静态方法返回一个包含这数个整数的数组。

给出示例代码(免积分下载),在MainActivity.java三处注释的地方,分别解注释再运行,就会认识得比较清楚了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值