Раньше я определял набор связанных констант, таких как Bundle
ключи, вместе в интерфейсе, как показано ниже:
public interface From{
String LOGIN_SCREEN = "LoginSCreen";
String NOTIFICATION = "Notification";
String WIDGET = "widget";
}
Это дает мне более удобный способ сгруппировать связанные константы вместе и использовать их путем статического импорта (не реализует). Я знаю , что Android
система также использует константы в точно так же , как Toast.LENTH_LONG
, View.GONE
.
Однако мне часто кажется, что они Java Enums
предоставляют гораздо лучший и эффективный способ представления константы.
Но есть проблема Performence в использовании enums
на Android
?
Проведя небольшое исследование, я запутался. От этого вопрос
? «Избегайте Перечисления Где Вам только нужен Ints» удален от кончиков производительности Android, стало ясно , что Google
сняли „Избегайте перечисления“ от его советов по повышению эффективности, но от его официальных учебных документов Осознайте накладные памяти раздела ясно говорит: «перечисления часто требует вдвое больше памяти, чем статические константы. Вам следует строго избегать использования перечислений на Android. " Это все еще в силе? (Скажем, в Java
версиях после 1.6)"
Еще одна проблема, которую я заметил, - это отправка enums
с intents
использованием, Bundle
я должен отправить их путем сериализации (то есть putSerializable()
, что я считаю дорогостоящей операцией по сравнению с примитивным putString()
методом, хотя и enums
предоставляет ее бесплатно).
Может кто-нибудь пояснить, какой из них лучше всего представляет то же самое Android
? Должен ли я строго избегать использования enums
на Android
?
Enum.ordinal()
вместо этого.Ответы:
Используйте,
enum
когда вам нужны его функции.Не избегайте этого строго .Перечисление Java более мощное, но если вам не нужны его возможности, используйте константы, они занимают меньше места и сами могут быть примитивными.
Когда использовать enum:
перегрузка метода - каждая константа перечисления имеет собственную реализацию метода
public enum UnitConverter{ METERS{ @Override public double toMiles(final double meters){ return meters * 0.00062137D; } @Override public double toMeters(final double meters){ return meters; } }, MILES{ @Override public double toMiles(final double miles){ return miles; } @Override public double toMeters(final double miles){ return miles / 0.00062137D; } }; public abstract double toMiles(double unit); public abstract double toMeters(double unit); }
больше данных - ваша одна константа содержит более одной информации, которую нельзя поместить в одну переменную
Когда не использовать enum:
вы можете принимать непрерывные данные
public class Month{ public static final int JANUARY = 1; public static final int FEBRUARY = 2; public static final int MARCH = 3; ... public static String getName(final int month){ if(month <= 0 || month > 12){ throw new IllegalArgumentException("Invalid month number: " + month); } ... } }
Перечисления занимают больше места
Константы занимают меньше места
источник
Если перечисления просто имеют значения, вам следует попробовать использовать IntDef / StringDef, как показано здесь:
https://developer.android.com/studio/write/annotations.html#enum-annotations
Пример: вместо:
enum NavigationMode {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}
ты используешь:
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}) @Retention(RetentionPolicy.SOURCE) public @interface NavigationMode {} public static final int NAVIGATION_MODE_STANDARD = 0; public static final int NAVIGATION_MODE_LIST = 1; public static final int NAVIGATION_MODE_TABS = 2;
и в функции, которая имеет его как параметр / возвращаемое значение, используйте:
@NavigationMode public abstract int getNavigationMode(); public abstract void setNavigationMode(@NavigationMode int mode);
Если перечисление сложное, используйте перечисление. Это не так уж плохо.
Чтобы сравнить перечисления с постоянными значениями, вы должны прочитать здесь:
Их пример - перечисление с двумя значениями. В файле dex требуется 1112 байт по сравнению со 128 байтами, когда используются постоянные целые числа. Имеет смысл, поскольку перечисления - это реальные классы, а не то, как они работают на C / C ++.
источник
IntDef
аннотацией, это будет. Что касается часов, то, думаю, тоже довольно ясно. У какого устройства больше мощности процессора, оперативной памяти и аккумулятора: телефона или часов? И какие из них нуждаются в программном обеспечении для большей производительности из-за этого?В дополнение к предыдущим ответам я бы добавил, что если вы используете Proguard (и вам обязательно нужно сделать это, чтобы уменьшить размер и запутать свой код), тогда ваш
Enums
будет автоматически преобразован@IntDef
везде, где это возможно:https://www.guardsquare.com/en/proguard/manual/optimizations
Поэтому, если у вас есть некоторые дискретные значения и какой-то метод должен позволять принимать только эти значения, а не другие значения того же типа, я бы использовал
Enum
, потому что Proguard сделает эту ручную работу по оптимизации кода за меня.А вот хороший пост об использовании перечислений от Джейка Уортона, взгляните на него.
источник
Нет. « Строго » означает, что они настолько плохи, что их вообще нельзя использовать. Возможно, проблемы с производительностью могут возникнуть в экстремальной ситуации, например, при выполнении многих, многих (тысяч или миллионов) операций с перечислениями (последовательных в потоке пользовательского интерфейса). Гораздо более распространены сетевые операции ввода-вывода, которые должны выполняться строго в фоновом потоке. Наиболее распространенное использование перечислений - это, вероятно, своего рода проверка типа - является ли объект тем или иным , который работает настолько быстро, что вы не сможете заметить разницу между одним сравнением перечислений и сравнением целых чисел.
Для этого нет общего практического правила. Используйте все, что вам подходит и помогает подготовить ваше приложение. Оптимизируйте позже - после того, как вы заметите узкое место, которое замедляет работу какого-либо аспекта вашего приложения.
источник
С Android P у Google нет ограничений / возражений по использованию перечислений
Документация изменилась там, где раньше рекомендовалось проявлять осторожность, но сейчас об этом не упоминается. https://developer.android.com/reference/java/lang/Enum
источник
Два факта.
1, Enum - одна из самых мощных функций JAVA.
2, Android-телефон обычно имеет много памяти.
Так что мой ответ - НЕТ. Я буду использовать Enum в Android.
источник
Мне нравится добавлять, что вы не можете использовать @Annotations, когда объявляете List <> или Map <>, где ключ или значение относятся к одному из ваших интерфейсов аннотаций. Вы получаете сообщение об ошибке «Аннотации здесь не разрешены».
enum Values { One, Two, Three } Map<String, Values> myMap; // This works // ... but ... public static final int ONE = 1; public static final int TWO = 2; public static final int THREE = 3; @Retention(RetentionPolicy.SOURCE) @IntDef({ONE, TWO, THREE}) public @interface Values {} Map<String, @Values Integer> myMap; // *** ERROR ***
Поэтому, когда вам нужно упаковать его в список / карту, используйте enum, поскольку они могут быть добавлены, но группы @annotated int / string не могут.
источник