曾经有一段时间,许多网上的 Android 性能调优的文章都提到,要尽可能避免在 Android 中使用 enum,由于使用 enum 会引入较大的性能损失。html
然而,最新的 Android 文档已经改变了这一说法。根据 Android VM 的开发者Elliot Hugues 的博客所述,过去的 Android 官网的性能优化指南并不许确,混杂了许多臆断。所以现在他们严格地依据事实,重写了Android 性能优化指南,开发者也应当以最新的文档为准。固然比较窘迫的是,Android 文档的更新并非同时改口,事实上就在同个 training 目录下的 管理应用内存一文中,就仍然保留了过期的避免使用 enum 的说法。java
之因此从新鼓励使用 enum ,其解释是:android
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 所带来的内存增长已经能够忽略。性能优化
尽管如此,在实际开发中仍然有可能遇到内存消耗较大的应用开发问题,那么此时,该如何优化枚举值的实现,以节约内存消耗呢?方案以下:ide
然而,其问题在于,直接使用没法实现枚举变量赋值的类型安全。且没法把多个枚举值概括到同一个枚举类型下。好比:性能
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 中,能够在 proguard.cfg 中加入参数 -Doptimization class/unboxing/enum
,从而自动将 enum 替换为 static final int。这样,也就无需担忧多余的内存问题了。this
IntDef 能够用于替代 int,其价值在于用@IntDef int var
限定赋值范围,实现类型安全。还用 @IntDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})
归集了散乱的 static final int 变量,以下代码所示:code
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 互转的方法,所以在想换转换较多的场景下,不如采起第二种优化方法。
====================================
若是您以为个人文章对您有所启迪,请点击文末的推荐按钮,您的鼓励将会成为我坚持写做的莫大激励。 by DesGemini