Intereting Posts
Opencv импортирует highgui в андроид-студии показывает ошибку. Невозможно решить (я добавил библиотеку, пока ошибка остается) Активность Android onDestroy () вызывает блокировку экрана BSSID против MAC-адреса? Android-чек имеет активный телефонный звонок В чем разница между sendStickyBroadcast и sendBroadcast в Android? В чем разница между drawableLeft и drawableStart в EditText? Связь Android между действиями без onActivityResult Получить расстояние между текущим местоположением и выбранным местом в андроиде Как получить все виды в действии? Webview в PDF игнорирует название работы Создание изображения с помощью специального текста в Android Невозможно открыть или разработать приложения в студии Android Android: предложение, требуемое для обновления просмотра ресайклера по элементу, выбранному из счетчика Разрешения для голосового поиска Недопустимое описание проекта при импорте проекта в Eclipse

Передача перечисления или объекта через намерение (лучшее решение)

У меня есть активность, когда при запуске нужен доступ к двум различным ArrayLists. Оба списка – это разные объекты, которые я создал сам.

В принципе мне нужен способ передать эти объекты в действие из намерения. Я могу использовать addExtras (), но для этого требуется совместимый с Parceable класс. Я мог бы сделать мои классы переданными сериализуемыми, но, как я понимаю, это замедляет работу программы.

Какие у меня варианты?

Могу ли я передать Enum?

Как вариант: есть ли способ передать параметры в конструктор активности из намерения?

Это старый вопрос, но все не упоминают, что Enums на самом деле являются Serializable и поэтому могут быть добавлены в намерение в качестве дополнительного. Как это:

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

Предложение использовать статические или прикладные широкие переменные – действительно плохая идея. Это действительно связывает вашу деятельность с системой управления государством, и ее трудно поддерживать, отлаживать и решать проблемы.


АЛЬТЕРНАТИВЫ:

Хороший момент был отмечен тедзиком о том, что решение, предоставленное Одериком, дает вам ошибку. Однако предложенная альтернатива немного крошится – некоторые используют (даже используя дженерики).

Если вы действительно обеспокоены тем, что вы добавляете перечисление в намерение, я предлагаю вместо этого следующие альтернативы:

ОПЦИЯ 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); 

ВАРИАНТ 2: (общий, многоразовый и отсоединенный от перечисления)

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

Вы можете сделать enum реализовать 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).

UPDATE: Обратите внимание на комментарий enum.values() что enum.values() выделяет новый массив при каждом вызове.

Вы можете передать перечисление через строку.

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

Поддерживаемые строки поддерживаются, вы должны иметь возможность передать значение перечисления вокруг без проблем.

Для передачи перечисления с помощью намерения вы можете преобразовать enum в integer.

Пример:

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

С наилучшими пожеланиями. 🙂

Если вам действительно нужно, вы можете сериализовать enum как String, используя name() и valueOf(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 вместо enum является фиктивным. Перечисления используются для упрощения чтения и упрощения вашего кода. Это был бы большой шаг назад в темные века, чтобы не использовать Enums.

О Oderik's post:

Вы можете сделать enum реализовать Parcelable, что довольно просто для перечислений:

Public enum MyEnum реализует Parcelable {…} Вы можете использовать Intent.putExtra (String, Parcelable).

Если вы определяете переменную MyEnum myEnum, тогда сделайте aim.putExtra («Parcelable1», myEnum), вы получите «Метод putExtra (String, Parcelable) неоднозначен для сообщения об ошибке типа Intent». Потому что существует также метод Intent.putExtra (String, Parcelable), а оригинальный тип «Enum» реализует интерфейс Serializable, поэтому компилятор не знает, какой именно метод (aim.putExtra (String, Parcelable / или Serializable)).

Предложите удалить интерфейс Parcelable из MyEnum и перенести основной код в пакетную реализацию Paralleable, как это (Father2 является Parcelable и содержит поле enum):

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

Мне нравится просто.

  • Активность Fred имеет два режима: HAPPY и SAD .
  • Создайте статическую IntentFactory которая создает для вас свое Intent . Передайте ему Mode вы хотите.
  • IntentFactory использует имя класса Mode как имя дополнительного.
  • IntentFactory преобразует Mode в String используя name()
  • При входе в onCreate используйте эту информацию для преобразования в Mode .
  • Вы можете использовать ordinal() и Mode.values() . Мне нравятся строки, потому что я могу видеть их в отладчике.

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

Вы можете использовать конструктор enum для перечисления, чтобы иметь примитивный тип данных ..

 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 как дополнительные функции, а затем вытащить его из перечисления, используя его значение.

Я думаю, ваш лучший выбор состоит в том, чтобы преобразовать эти списки во что-то существенное, например строку (или карту?), Чтобы получить ее в Activity. Затем Activity будет преобразовывать его обратно в массив.

Реализация пользовательских parcelables – это боль в шее IMHO, поэтому я мог бы избежать этого, если это возможно.

Рассмотрим следующий enum ::

 public static enum MyEnum { ValueA, ValueB } а 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.