Передача перечислений через вспомогательные интерфейсы

Поскольку перечисления не являются примитивными типами, каков наиболее эффективный способ передать перечисление через вспомогательный интерфейс в Android? Есть ли способ сначала преобразовать перечисление в порядковый?


person Phillip    schedule 08.02.2011    source источник
comment
Взгляните на комментарий Чарли Коллинза. Это совершенно верно: по возможности избегайте перечислений.   -  person Cristian    schedule 08.02.2011
comment
@Cristian, к этому нужно отнестись с недоверием. перечисления - хороший дизайн. есть причина, по которой Android не удаляет перечисления с языка.   -  person Jeffrey Blattman    schedule 08.08.2013
comment
Это правда, чувак. Однако я думаю, что они не переместили его, потому что это не так просто. Они по-прежнему используют javac перед обработкой байт-кода. В любом случае ... Я люблю перечисления и использую их, когда они делают вещи ясными и элегантными.   -  person Cristian    schedule 09.08.2013
comment
Перечисления прекрасно подходят для кода приложения. Авторы фреймворка работают с другим набором ограничений. (Сравните, например, то, как MFC избегает виртуалов во многих своих основных классах.) В частности, для Android ранние тесты показали, что перечисления потребляют значительно больше памяти, чем константы, поэтому структура их избегает. YMMV. Фактически, ваш опыт будет варьироваться, поэтому делайте правильные вещи для своего приложения, а не просто делайте то, что делают все остальные.   -  person Ian Ni-Lewis    schedule 26.05.2016
comment
Где-то в глубокой сети Google дал нам добро на использование перечислений в коде Android. Где-то около 600 байт для перечисления. А телефоны прошли долгий путь со времен Android 1.0. Действуй.   -  person Robin Davies    schedule 21.04.2019


Ответы (3)


Я просто использую

String enumString = myEnum.name() 

(с MyEnum в качестве перечисления и myEnum в качестве значения), чтобы получить представление String, а затем

MyEnum myEnum = MyEnum.valueOf(enumString) 

для восстановления перечисления из строкового представления.

Использование Ordinals может быть немного быстрее, но если я могу добавить Enums позже, это с большей вероятностью сломает старый код.

// Изменить: поскольку мне не нравится, когда тип возвращаемого значения String, я реализовал Parcellable, как указано здесь: Передача перечисления или объекта через намерение (лучшее решение)

import android.os.Parcel; import android.os.Parcelable;

enum InitResponse implements Parcelable {
// Everything is fine.
SUCCESS,
// Something else
FOO;


@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(final Parcel dest, final int flags) {
    dest.writeString(name());
}

public static final Creator<InitResponse> CREATOR = new Creator<InitResponse>() {
    @Override
    public InitResponse createFromParcel(final Parcel source) {
        return InitResponse.valueOf(source.readString());
    }

    @Override
    public InitResponse[] newArray(final int size) {
        return new InitResponse[size];
    }
};

}
person domenukk    schedule 20.05.2012
comment
В итоге я объединил этот подход с Parcellable-Implementation из stackoverflow.com/questions/2836256/, в результате чего получился отредактированный код выше. - person domenukk; 22.05.2012

Непримитивные типы, кроме String, требуют указателя направления. Указатели направления включают in, out и inout.

Взгляните на официальную документацию для этого: http://developer.android.com/guide/developing/tools/aidl.html#aidlsyntax.

Кроме того, вы можете рассмотреть возможность передачи строкового или порядкового представления перечисления и при необходимости перевести его обратно. Это взято из 2-го издания Effective Java:

// Implementing a fromString method on an enum type
private static final Map<String, Operation> stringToEnum = new HashMap<String, Operation>();
static { // Initialize map from constant name to enum constant
    for (Operation op : values())
        stringToEnum.put(op.toString(), op);
} // Returns Operation for string, or null if string is invalid
public static Operation fromString(String symbol) {
    return stringToEnum.get(symbol);
}

В приведенном выше случае Operation - это enum.


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

public enum Badges{
    GOLD, SILVER, BRONZE;
}

// somewhere else:
int ordinal = Badges.SILVER.ordinal();// this should be 1
person Cristian    schedule 08.02.2011
comment
Вам также следует подумать о том, чтобы полностью избегать перечислений (в проекте Android), если вы можете в этом помочь. developer.android.com/guide/practices/design/ - person Charlie Collins; 08.02.2011
comment
К сожалению, у меня нет возможности избежать перечислений; это совместный проект. Могу ли я извлечь порядковый номер значения перечисления? - person Phillip; 09.02.2011
comment
@CharlieCollins Это Совет был отозван. - person Autodidact; 20.01.2012

Да, вы можете передавать перечисления через AIDL, но вам нужно реализовать Parcelable для типа перечисления.

1: Реализация Parcelable.

public enum RepeatMode implements Parcelable {
    NoRepeat,
    RepeatAll,
    RepeatTrack,
    ;

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(toInteger());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<RepeatMode> CREATOR = new Creator<RepeatMode>() {
        @Override
        public RepeatMode createFromParcel(Parcel in) {
            return RepeatMode.fromInteger(in.readInt());
        }

        @Override
        public RepeatMode[] newArray(int size) {
            return new RepeatMode[size];
        }
    };

    public int toInteger() { return this.ordinal(); }
    public static RepeatMode fromInteger(int value)
    {
        return values()[value];
    }
}
  1. Импорт:

    RepeatMode.aidl: пакет com.cyberdyne.media;

    parcelable RepeatMode;

  2. И не забудьте пометить аргументы перечисления как аргументы.

Кажется очевидным, если подумать. Но я уверен, что Google не использует много перечислений в интерфейсах IBinder. Хотя я это делаю. (Спасибо студии Android за предоставление «Реализовать Parcelable», которое не работает полностью для перечислений, но упрощает работу).

Обсуждение перечислений Android:

Рекомендации по использованию перечислений в Android были отозваны много месяцев назад. Вы торгуете примерно 200 байтами исполняемого файла на ужасный, ужасный код. Телефоны прошли долгий путь со времен Android 1.0. Это и ежу понятно. Используйте перечисления. (Или используйте безумную систему атрибутов, основанную на Kotlin, которую использует Google. Удачи вам с этим.)

Официальные знания Java, восходящие к спецификации оригинального языка Java, не рекомендуют использовать голый порядковый номер (). Обоснование: в глубоком будущем разработчики могут непреднамеренно переупорядочить порядковые номера и сломать вещи. Честно говоря, я считаю, что это напыщенная чушь Java. Я долго боролся с этим, и после долгих самоанализа я сдался.

public enum Badges {
   GOLD,SILVER, BRONZE; // Must match @array/badge_states 

   public int toInteger() { return this.ordinal(); }
   public static Badges fromInteger(int value) { return values()[value]);
}

По крайней мере, он отмечает класс как тот, который, вероятно, сохраняет целые числа. И комментарий никогда не повредит, и он делает приемную часть упорядоченных перечислений немного красивее (и чуть-чуть безопаснее).

person Robin Davies    schedule 21.04.2019