曾經有一段時間,許多網上的 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