通过一个意图传递枚举或对象(最好的解决scheme)

我有一个活动,启动时需要访问两个不同的ArrayList。 两个列表都是我自己创build的不同对象。

基本上我需要一种方法将这些对象从一个意图传递给活动。 我可以使用addExtras(),但是这需要一个Parceable兼容的类。 我可以让我的类通过可序列化,但据我了解这会减慢程序。

我有什么select?

我可以通过一个枚举?

顺便说一句:有没有一种方法可以将参数从一个Intent传递给一个Activity构造器?

这是一个古老的问题,但每个人都没有提到,枚举实际上是可Serializable ,因此可以完美地添加到一个意图作为一个额外的。 喜欢这个:

 public enum AwesomeEnum { SOMETHING, OTHER; }; intent.putExtra("AwesomeEnum", AwesomeEnum.SOMETHING); AwesomeEnum result = (AwesomeEnum) intent.getSerializableExtra("AwesomeEnum"); 

build议使用静态或应用程序范围的variables是一个非常糟糕的主意。 这真的把你的活动与国家pipe理体系结合起来,难以维护,debugging和解决问题。


备择scheme:

tedzyc注意到Oderik提供的解决scheme给你一个错误。 然而,提供的替代是有点崩溃 – 一些使用(即使使用generics)。

如果你真的担心添加枚举的意图,我build议这些替代方法:

选项1:

 public enum AwesomeEnum { SOMETHING, OTHER; private static final String name = AwesomeEnum.class.getName(); public void attachTo(Intent intent) { intent.putExtra(name, ordinal()); } public static AwesomeEnum detachFrom(Intent intent) { if(!intent.hasExtra(name)) throw new IllegalStateException(); return values()[intent.getIntExtra(name, -1)]; } } 

用法:

 // Sender usage AwesomeEnum.SOMETHING.attachTo(intent); // Receiver usage AwesomeEnum result = AwesomeEnum.detachFrom(intent); 

scheme2 🙁通用的,可重用的和从枚举中分离的)

 public final class EnumUtil { public static class Serializer<T extends Enum<T>> extends Deserializer<T> { private T victim; @SuppressWarnings("unchecked") public Serializer(T victim) { super((Class<T>) victim.getClass()); this.victim = victim; } public void to(Intent intent) { intent.putExtra(name, victim.ordinal()); } } public static class Deserializer<T extends Enum<T>> { protected Class<T> victimType; protected String name; public Deserializer(Class<T> victimType) { this.victimType = victimType; this.name = victimType.getName(); } public T from(Intent intent) { if (!intent.hasExtra(name)) throw new IllegalStateException(); return victimType.getEnumConstants()[intent.getIntExtra(name, -1)]; } } public static <T extends Enum<T>> Deserializer<T> deserialize(Class<T> victim) { return new Deserializer<T>(victim); } public static <T extends Enum<T>> Serializer<T> serialize(T victim) { return new Serializer<T>(victim); } } 

用法:

 // Sender usage EnumUtil.serialize(AwesomeEnum.Something).to(intent); // Receiver usage AwesomeEnum result = EnumUtil.deserialize(AwesomeEnum.class).from(intent); 

你可以让你的枚举实现Parcelable,这对于枚举来说非常简单:

 public enum MyEnum implements Parcelable { VALUE; @Override public int describeContents() { return 0; } @Override public void writeToParcel(final Parcel dest, final int flags) { dest.writeInt(ordinal()); } public static final Creator<MyEnum> CREATOR = new Creator<MyEnum>() { @Override public MyEnum createFromParcel(final Parcel source) { return MyEnum.values()[source.readInt()]; } @Override public MyEnum[] newArray(final int size) { return new MyEnum[size]; } }; } 

然后可以使用Intent.putExtra(String,Parcelable)。

更新:请注意wreckgar的评论, enum.values()在每次调用分配一个新的数组。

你可以通过一个string传递一个枚举。

 public enum CountType { ONE, TWO, THREE } private CountType count; count = ONE; String countString = count.name(); CountType countToo = CountType.valueOf(countString); 

给定的string被支持,你应该能够传递的枚举值没有问题。

为了通过意图传递枚举,可以将枚举转换为整数。

例如:

 public enum Num{A ,B} 

发送(枚举为整数):

 Num send = Num.A; intent.putExtra("TEST", send.ordinal()); 

接收(整数到枚举):

 Num rev; int temp = intent.getIntExtra("TEST", -1); if(temp >= 0 && temp < Num.values().length) rev = Num.values()[temp]; 

最好的祝福。 🙂

如果你真的需要,你可以使用name()valueOf(String)作为一个string序列化一个枚举,如下所示:

  class Example implements Parcelable { public enum Foo { BAR, BAZ } public Foo fooValue; public void writeToParcel(Parcel dest, int flags) { parcel.writeString(fooValue == null ? null : fooValue.name()); } public static final Creator<Example> CREATOR = new Creator<Example>() { public Example createFromParcel(Parcel source) { Example e = new Example(); String s = source.readString(); if (s != null) e.fooValue = Foo.valueOf(s); return e; } } } 

这显然不工作,如果你的枚举有可变状态(他们不应该,真的)。

有可能让你的Enum实现Serializable,然后你可以通过Intent传递它,因为有一个方法将它作为一个序列化来传递。 使用int而不是枚举的build议是伪造的。 枚举用于使代码更易于阅读和维护。 它会向黑暗时代倒退一大步,不能使用枚举。

关于Oderik的post:

你可以让你的枚举实现Parcelable,这对于枚举来说非常简单:

公共枚举MyEnum实现Parcelable {…}你可以比使用Intent.putExtra(String,Parcelable)。

如果你定义了一个MyEnumvariablesmyEnum,然后执行intent.putExtra(“Parcelable1”,myEnum),你会得到一个“方法putExtra(String,Parcelable)对于Intenttypes错误信息”。 因为还有一个Intent.putExtra(String,Parcelable)方法,并且原来的Enumtypes本身实现了Serializable接口,所以编译器不知道select哪个方法(intent.putExtra(String,Parcelable /或Serializable))。

build议从MyEnum中移除Parcelable接口,并将核心代码移动到wrap类的Parcelable实现中,像这样(Father2是一个Parcelable并包含枚举字段):

 public class Father2 implements Parcelable { AnotherEnum mAnotherEnum; int mField; public Father2(AnotherEnum myEnum, int field) { mAnotherEnum = myEnum; mField = field; } private Father2(Parcel in) { mField = in.readInt(); mAnotherEnum = AnotherEnum.values()[in.readInt()]; } public static final Parcelable.Creator<Father2> CREATOR = new Parcelable.Creator<Father2>() { public Father2 createFromParcel(Parcel in) { return new Father2(in); } @Override public Father2[] newArray(int size) { return new Father2[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mField); dest.writeInt(mAnotherEnum.ordinal()); } } 

那么我们可以这样做:

 AnotherEnum anotherEnum = AnotherEnum.Z; intent.putExtra("Serializable2", AnotherEnum.X); intent.putExtra("Parcelable2", new Father2(AnotherEnum.X, 7)); 

你可以使用枚举的构造函数枚举有原始数据types..

 public enum DaysOfWeek { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7); private int value; private DaysOfWeek(int value) { this.value = value; } public int getValue() { return this.value; } private static final SparseArray<DaysOfWeek> map = new SparseArray<DaysOfWeek>(); static { for (DaysOfWeek daysOfWeek : DaysOfWeek.values()) map.put(daysOfWeek.value, daysOfWeek); } public static DaysOfWeek from(int value) { return map.get(value); } } 

你可以使用传递int作为额外的东西,然后使用它的值从枚举。

我喜欢简单。

  • Fred活动有两种模式 – HAPPYSAD
  • 创build一个静态IntentFactory ,为您创build您的Intent 。 把它传递给你想要的Mode
  • IntentFactory使用Mode类的名称作为额外的名称。
  • IntentFactory使用name()Mode转换为String
  • 进入onCreate使用此信息转换回Mode
  • 你也可以使用ordinal()Mode.values() 。 我喜欢string,因为我可以在debugging器中看到它们。

     public class Fred extends Activity { public static enum Mode { HAPPY, SAD, ; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.betting); Intent intent = getIntent(); Mode mode = Mode.valueOf(getIntent().getStringExtra(Mode.class.getName())); Toast.makeText(this, "mode="+mode.toString(), Toast.LENGTH_LONG).show(); } public static Intent IntentFactory(Context context, Mode mode){ Intent intent = new Intent(); intent.setClass(context,Fred.class); intent.putExtra(Mode.class.getName(),mode.name()); return intent; } } 

我认为你最好的select就是将这些列表转换成可以像string(或地图? 然后Activity将不得不将其转换回数组。

实现自定义parcelables是在脖子恕我直言,所以我会尽可能避免它的痛苦。

考虑以下枚举::

 public static enum MyEnum { ValueA, ValueB } 

传球::

  Intent mainIntent = new Intent(this,MyActivity.class); mainIntent.putExtra("ENUM_CONST", MyEnum.ValueA); this.startActivity(mainIntent); 

在其他活动中使用::

MyEnum myEnum =(MyEnum)intent.getSerializableExtra(“ENUM_CONST”);

不要使用枚举。 原因#78不使用枚举。 :)使用整数,可以很容易地通过Bundle和Parcelable进行远程访问。