通过一个意图传递枚举或对象(最好的解决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活动有两种模式 –
HAPPY
和SAD
。 - 创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进行远程访问。