当前位置: 首页 > 知识库问答 >
问题:

我应该严格避免在Android上使用枚举吗?

濮阳默
2023-03-14

我曾在如下界面中定义一组相关常量,如捆绑键:

public interface From{
    String LOGIN_SCREEN = "LoginSCreen";
    String NOTIFICATION = "Notification";
    String WIDGET = "widget";
}

这为我提供了一种更好的方法来将相关的常量组合在一起,并通过静态导入(而不是实现)来使用它们。我知道Android框架也以与Toast相同的方式使用常量。LENTH_LONG查看。GONE.

然而,我经常觉得javaenum提供了更好、更强大的方法来表示常量。

但是在Android上使用枚举是否存在性能问题?

经过一番研究,我最终陷入了困惑。从Android的性能提示中删除了“避免只需要整数的枚举”这个问题?很明显,Google已经从其性能提示中删除了“避免枚举”,但从其官方培训文档“注意内存开销”一节中,它清楚地说:“枚举通常需要的内存是静态的两倍以上常数。您应该严格避免在Android上使用枚举。“这仍然有效吗?(比如在Java1.6之后的版本中)

我观察到的另一个问题是,使用Bundle意图发送enum,我应该通过序列化发送它们(即putSerializable(),我认为与基元putString()方法相比,这是一个昂贵的操作,尽管enum是免费提供的)。

有人能澄清一下,在Android中,哪一种方式是最好的表达方式吗?我是否应该严格避免在Android上使用enums


共有3个答案

苏乐童
2023-03-14

除了前面的答案之外,我还要补充一点,如果您使用Proguard(并且您肯定应该这样做以减小大小并混淆代码),那么您的枚举将自动转换为@IntDef,只要有可能:

https://www.guardsquare.com/en/proguard/manual/optimizations

类/取消装箱/枚举

尽可能将枚举类型简化为整数常量。

因此,如果您有一些离散值,并且某些方法应该只允许取这些值,而不允许取其他相同类型的值,那么我将使用Enum,因为Proguard将为我优化代码。

这里有一篇关于使用杰克·沃顿枚举的好文章,请看一下。

作为一名库开发人员,我认识到应该进行这些小优化,因为我们希望对消费应用程序的大小、内存和性能产生尽可能小的影响。但重要的是要认识到[…]在适当的情况下,将枚举与整数值放在公共API中是完全正确的。重要的是要知道做出明智决策的区别

马魁
2023-03-14

如果枚举只有值,则应尝试使用IntDef/StringDef,如下所示:

https://developer.android.com/studio/write/annotations.html#enum-注释

例如:代替:

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

如果枚举很复杂,请使用枚举。没那么糟。

要比较枚举与常量值,请阅读以下内容:

http://hsc.com/Blog/Best-Practices-For-Memory-Optimization-on-Android-1

他们的示例是一个具有2个值的枚举。与使用常量整数时的128字节相比,dex文件需要1112字节。这很有意义,因为枚举是实类,而不是它在C/C上的工作方式。

易成双
2023-03-14

需要其功能时,请使用enum。不要严格地回避它。

JavaEnum功能更强大,但如果您不需要它的特性,可以使用常量,它们占用的空间更少,而且它们本身也可以是原语。

>

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

更多数据-一个常量包含多个不能放入一个变量中的信息

>

  • 您可以接受一种类型的所有值,并且常量只包含这些最常用的值
  • 您可以接受连续数据

    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);
            }
    
            ...
        }
    }
    
    • 对枚举常量的单个引用占用4个字节
    • 常量没有引用,因此它是纯数据(即使它是引用,枚举实例也将是对另一引用的引用)
    • 常量可以添加到现有类中-无需添加其他类
    • 可以是内联常量;它带来了扩展的编译时特性(如空检查、查找死代码等)

  •  类似资料:
    • 问题内容: 我曾经在如下所示的接口中一起定义了一组相关的常量(如键): 这为我提供了一种更好的方式将相关常量分组在一起,并通过进行静态导入(而非实现)来使用它们。我知道框架也使用像一样的常量,。 但是,我经常感到,提供代表常数的更好,更强大的方法。 但是使用on 会有性能问题吗? 经过一番研究,我最终陷入了混乱。从这个问题中, 从Android的性能提示中删除了“避免枚举,您只需要整数吗?”很明显

    • 问题内容: 有时是有用的,例如,如果我为网站上的所有链接(例如选择器)定义了通用样式,但是当我要覆盖某些规则时,可以有以下选择: 使用更具体(更长)的选择器 采用 哪种方法更好,可能有一些指导原则? 问题答案: 使用非常,非常谨慎- 它会覆盖刚才的一切,甚至是内联样式和混乱在低于显而易见的方式与样式规则“梯级”,让CSS的名字。它很容易使用不当,而且容易成倍增加,尤其是在滥用时。您可以轻松地得出一

    • 问题内容: 我读到应该避免赞成和。我对弄乱Loop并没有信心,也没有完全理解Codex。 下面的代码是否使用?如果是,并且由于应该避免,那么您能建议一种不使用但仍然完成相同任务的方法吗? 此代码用于按随机或按价格对帖子进行排序。 。 使用此代码将链接A(随机)和链接B(价格)发布在我的菜单中。因此,网站的访问者只需单击链接即可对帖子进行排序。 问题答案: 我已经针对WPSE这个主题做了非常详细的解

    • 问题内容: 今天,我有一个同事建议我重构代码,以使用label语句控制通过我创建的2个嵌套的for循环的流。我以前从未使用过它们,因为我个人认为它们会降低程序的可读性。如果论点足够扎实,我愿意改变使用它们的想法。人们对标签陈述有何看法? 问题答案: 如果您可以跳过两个循环(或一个包含switch语句的循环),则许多算法的表达会更容易。不要为此感到难过。另一方面,它可能表明解决方案过于复杂。因此,退

    • 对于与PropertyValueFactory相关的问题,许多回答(和评论)建议避免使用该类和其他类似类。使用这个类有什么问题?

    • 问题内容: 在某些情况下,我喜欢将缓冲显示为的功能,这会给我带来好处,但程序包名称使我有点担心在生产代码中使用它。我了解它 主要 用于测试,但是不确定我是否在生产代码中使用它时遇到麻烦。 我在吸引命运吗? 问题答案: 您不应在生产中使用此代码。无论您要实现什么目标。 最终目的是促进 测试 ,因此始终会在考虑测试的情况下进行扩展,优化( 重写) 。只要可以使该软件包更好地进行测试,就可以在该软件包中