[英]Should I strictly avoid using enums on Android?
I used to define a set of related constants like Bundle
keys together in an interface like below:我曾经在如下界面中定义了一组相关的常量,例如
Bundle
键:
public interface From{
String LOGIN_SCREEN = "LoginSCreen";
String NOTIFICATION = "Notification";
String WIDGET = "widget";
}
This provides me a nicer way to group related constants together and used them by making a static import (not implements).这为我提供了一种更好的方法来将相关常量组合在一起,并通过进行静态导入(而不是实现)来使用它们。 I know
Android
framework also uses the constants in same way like Toast.LENTH_LONG
, View.GONE
.我知道
Android
框架也以与Toast.LENTH_LONG
、 View.GONE
相同的方式使用常量。
However, I often feel that the Java Enums
provide much better and powerful way to represent the constant.然而,我经常觉得
Java Enums
提供了更好、更强大的方式来表示常量。
But is there a performence issue in using enums
on Android
?但是在
Android
上使用enums
是否存在性能问题?
With a bit of research I ended up in confusion.经过一些研究,我最终陷入了困惑。 From this question "Avoid Enums Where You Only Need Ints” removed from Android's performance tips? it's clear that
Google
has removed "Avoid enums" from its performance tips, but from it's official training docs Be aware of memory overhead section it clearly says: "Enums often require more than twice as much memory as static constants.从这个问题“Avoid Enums Where You Only Need Ints”中删除了Android的性能提示?很明显
Google
已经从它的性能提示中删除了“避免枚举” ,但是从它的官方培训文档注意内存开销部分它清楚地说: “枚举通常需要比静态常量多两倍的内存。 You should strictly avoid using enums on Android." Is this still holds good? (say in Java
versions after 1.6)你应该严格避免在 Android 上使用枚举。”这仍然有效吗?(比如 1.6 之后的
Java
版本)
One more issue that I observed is to send enums
across intents
using Bundle
I should send them by serializing (ie putSerializable()
, that I think an expensive operation compared to primitive putString()
method, eventhough enums
provides it for free).我观察到的另一个问题是使用
Bundle
跨intents
发送enums
我应该通过序列化发送它们(即putSerializable()
,我认为与原始putString()
方法相比,这是一种昂贵的操作,尽管enums
是免费提供的)。
Can someone please clarify which one is the best way to represent the same in Android
?有人可以澄清哪一种是在
Android
表示相同的最佳方式吗? Should I strictly avoid using enums
on Android
?我应该严格避免在
Android
上使用enums
吗?
Use enum
when you need its features.当您需要其功能时使用
enum
。 Don't avoid it strictly .不要严格避免它。
Java enum is more powerful, but if you don't need its features, use constants, they occupy less space and they can be primitive itself. Java enum 更强大,但如果你不需要它的特性,使用常量,它们占用更少的空间并且它们本身可以是原始的。
method overloading - every enum constant has its own implementation of a method方法重载 - 每个枚举常量都有自己的方法实现
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); }
more data - your one constant contains more than one information that cannot be put in one variable更多数据 - 你的一个常量包含多个不能放在一个变量中的信息
you can accept continuous data你可以接受连续数据
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); } ... } }
If the enums simply have values, you should try to use IntDef/StringDef , as shown here:如果枚举只有值,您应该尝试使用 IntDef/StringDef ,如下所示:
https://developer.android.com/studio/write/annotations.html#enum-annotations https://developer.android.com/studio/write/annotations.html#enum-annotations
Example: instead of :示例:而不是:
enum NavigationMode {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}
you use:你用:
@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;
and in the function that has it as a parameter/returned value , use:并在将其作为参数/返回值的函数中,使用:
@NavigationMode
public abstract int getNavigationMode();
public abstract void setNavigationMode(@NavigationMode int mode);
In case the enum is complex, use an enum.如果枚举很复杂,请使用枚举。 It's not that bad.
它没有那么坏。
To compare enums vs constant values, you should read here:要比较枚举与常量值,您应该在这里阅读:
http://hsc.com/Blog/Best-Practices-For-Memory-Optimization-on-Android-1
http://hsc.com/Blog/Best-Practices-For-Memory-Optimization-on-Android-1
Their example is of an enum with 2 values.他们的例子是一个有 2 个值的枚举。 It takes 1112 bytes in dex file compared to 128 bytes when constant integers are used .
与使用常量整数时的 128 字节相比,它在 dex 文件中需要 1112 字节。 Makes sense, as enums are real classes, as opposed to how it works on C/C++ .
有道理,因为枚举是真正的类,而不是它在 C/C++ 上的工作方式。
In addition to previous answers, I would add that if you are using Proguard (and you should definitely do it to reduce size and obfuscate your code), then your Enums
will be automatically converted to @IntDef
wherever it is possible:除了以前的答案,我想补充一点,如果你正在使用Proguard的(和你一定要做到这一点,以减少大小和模糊处理的代码),那么你的
Enums
将被自动转换为@IntDef
无论它是可能的:
https://www.guardsquare.com/en/proguard/manual/optimizationshttps://www.guardsquare.com/en/proguard/manual/optimizations
class/unboxing/enum
类/拆箱/枚举
Simplifies enum types to integer constants, whenever possible.
尽可能将枚举类型简化为整数常量。
Therefore, if you have some discrete values and some method should allow to take only this values and not others of the same type, then I would use Enum
, because Proguard will make this manual work of optimizing code for me.因此,如果您有一些离散值并且某些方法应该只允许采用这些值而不是其他相同类型的值,那么我将使用
Enum
,因为 Proguard 将为我进行优化代码的手动工作。
And here is a good post about using enums from Jake Wharton, take a look at it.这是一篇关于使用 Jake Wharton 枚举的好文章,请看一看。
As a library developer, I recognize these small optimizations that should be done as we want to have as little impact on the consuming app's size, memory, and performance as possible.
作为库开发人员,我认为应该进行这些小的优化,因为我们希望对消费应用程序的大小、内存和性能产生尽可能小的影响。 But it's important to realize that [...] putting an enum in your public API vs. integer values where appropriate is perfectly fine.
但重要的是要意识到 [...] 在你的公共 API 中放置一个枚举而不是整数值是完全没问题的。 Knowing the difference to make informed decisions is what's important
了解差异以做出明智的决定是重要的
With Android P, google has no restriction/objection in using enums使用 Android P,谷歌在使用枚举方面没有限制/反对
The documentation has changed where before it was recommended to be cautious but it doesn't mention it now.文档已经更改了之前建议谨慎的地方,但现在没有提及。 https://developer.android.com/reference/java/lang/Enum
https://developer.android.com/reference/java/lang/Enum
Should I strictly avoid using enums on Android?
我应该严格避免在 Android 上使用枚举吗?
No. " Strictly " means they are so bad, they should not be used at all.不。“严格”意味着它们太糟糕了,根本不应该使用它们。 Possibly a performance issues might arise in an extreme situation like many many many (thousands or millions of) operations with enums (consecutive on the ui thread).
在极端情况下可能会出现性能问题,例如使用枚举(在 ui 线程上连续进行)的许多(数千或数百万)操作。 Far more common are the network I/O operations that should strictly happen in a background thread.
更常见的是应该严格发生在后台线程中的网络 I/O 操作。 The most common usage of enums is probably some kind of type check - whether an object is this or that which is so fast you won't be able to notice a difference between a single comparison of enums and a comparison of integers.
枚举最常见的用法可能是某种类型的检查——一个对象是这个还是那个,它太快了,你将无法注意到枚举的单个比较和整数的比较之间的区别。
Can someone please clarify which one is the best way to represent the same in Android?
有人可以澄清哪一种是在Android中表示相同的最佳方式吗?
There is no general rule of thumb for this.对此没有一般的经验法则。 Use whatever works for you and helps you get your app ready.
使用适合您的任何东西并帮助您准备好您的应用程序。 Optimize later - after you notice there's a bottleneck that slows some aspect of your app.
稍后优化 - 在您注意到有一个瓶颈会减慢您的应用程序的某些方面。
Two facts.两个事实。
1, Enum is one of the most powerful feature in JAVA. 1、枚举是JAVA中最强大的特性之一。
2, Android phone usually has a LOT of memory. 2、Android手机通常有很多内存。
So my answer is NO.所以我的答案是否定的。 I will use Enum in Android.
我将在 Android 中使用 Enum。
I like to add, that you can not use @Annotations when you declare a List<> or Map<> where either key or value is of one of your annotation interfaces.我想补充一点,当您声明 List<> 或 Map<> 时不能使用 @Annotations,其中键或值是您的注释接口之一。 You get the error "Annotations are not allowed here".
您收到错误“此处不允许使用注释”。
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 ***
So when you need to pack it into a list/map, use enum, as they can be added, but @annotated int/string groups can not.因此,当您需要将其打包到列表/映射中时,请使用 enum,因为它们可以添加,但 @annotated int/string 组不能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.