android 列表枚举,Android 中实现枚举的方案选择

Android 中实现枚举的方案选择:enum、static final 与 IntDef

引言:

曾经有一段时间,许多网上的 Android 性能调优的文章都提到,要尽量避免在 Android 中使用 enum,因为使用 enum 会引入较大的性能损失。这个当时和同事、领导进行了长时间的讨论、验证,最后还是放弃了enum。

然而,最新的 Android 文档已经改变了这一说法。根据 Android VM 的开发者Elliot Hugues 的博客所述,过去的 Android 官网的性能优化指南并不准确,混杂了许多臆断。因此如今他们严格地依据事实,重写了Android 性能优化指南,开发者也应当以最新的文档为准。当然比较窘迫的是,Android 文档的更新并不是同时改口,事实上就在同个 training 目录下的 管理应用内存一文中,就仍然保留了过时的避免使用 enum 的说法。

最新的观点解释:

之所以重新鼓励使用 enum ,其解释是:

Android 2.2 及以下系统上,使用 enum 的确会引发较大的性能损耗。主要是内存上的消耗,enum 远大于使用 static final int。

在 Android 2.3 及以后的系统中,之前的一些 enum 的性能问题已被 JIT 所优化。此时,虽然 enum 相比于 static final int,内存仍然有所增加,但已经是可以接受的了。加之 Android 2.2 到如今的 Android 7.0,Android 手机的内存配置突飞猛进,从256MB跃升至6GB,enum 所带来的内存增加已经可以忽略。

尽管如此,在实际开发中仍然有可能遇到内存消耗较大的应用开发问题,那么此时,该如何优化枚举值的实现,以节约内存消耗呢?方案如下:

直接使用 static final int

然而,其问题在于,直接使用无法实现枚举变量赋值的类型安全。且无法把多个枚举值归纳到同一个枚举类型下。比如:

private static final int MONDAY = 0;

private static final int TUESDAT= 1;

private static final int WEDNESDAY = 2;

private static final int THURSDAY = 3;

private static final int FRIDAY = 4;

private static final int SATURDAY = 5;

private static final int SUNDAY = 6;

private static final int JANUARY = 7;

private int day = JANUARY;

显然,此时 int 就未能实现赋值的类型检查,也未能把多个枚举值归纳到同一个枚举类型下。

Android Proguard 优化

在 Android Proguard 中,可以在 proguard.cfg 中加入参数 -Doptimization class/unboxing/enum,从而自动将 enum 替换为 static final int。这样,也就无需担心多余的内存问题了。

使用 IntDef 注解替代 int

IntDef 可以用于替代 int,其价值在于用@IntDef int var限定赋值范围,实现类型安全。还用@IntDef({SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})归集了散乱的 static final int 变量,如下代码所示:

public class MainActivity extends Activity{

public static final int SUNDAY = 0;

public static final int MONDAY = 1;

public static final int TUESDAY = 2;

public static final int WEDNESDAY = 3;

public static final int THURSDAY = 4;

public static final int FRIDAY = 5;

public static final int SATURDAY = 6;

@IntDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})

@Retention(RetentionPolicy.SOURCE)

public @interface WeekDays {}

@WeekDays int currentDay = SUNDAY;

@Override

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

setCurrentDay(WEDNESDAY);

@WeekDays int today = getCurrentDay();

switch (today){

case SUNDAY:

break;

case MONDAY:

break;

case TUESDAY:

break;

case WEDNESDAY:

break;

case THURSDAY:

break;

case FRIDAY:

break;

case SATURDAY:

break;

default:

break;

}

}

public void setCurrentDay(@WeekDays int currentDay){

this.currentDay = currentDay;

}

@WeekDays

public int getCurrentDay(){

return currentDay;

}

}

然而,IntDef 的缺点在于无法优雅地把 int 转为 IntDef,尤其在一个枚举值是服务端下发的时候。强行的实现会变的极为尴尬:

@WeekDays

public int getDay(int value){

switch (value){

case 0:

return SUNDAY;

case 1:

return MONDAY;

case 2:

return TUESDAY;

case 3:

return WEDNESDAY;

case 4:

return THURSDAY;

case 5:

return FRIDAY;

case 6:

return SATURDAY;

}

此时,在枚举值较少的时候还能忍,较多的时候代码就会变得非常丑陋。本质是因为,@IntDef 缺少像 Enum.values()Enum.ordinal() 等等

int 与 enum 与 String 互转的方法,因此在想换转换较多的场景下,不如采取第二种优化方法。

总结:建议暂时还使用static final。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值