1. 程式人生 > 程式設計 >Android使用註解代替列舉節省系統記憶體開銷的方法

Android使用註解代替列舉節省系統記憶體開銷的方法

Java5以後開始支援列舉型別,列舉型別使用起來非常方便,其重要的作用是作為型別安全使用的。如果在不考慮系統記憶體開銷的情況下大量的使用列舉也不會有什麼問題。但是移動端還是需要注意的。

android系統在應用啟動後會給應用單獨分配一塊記憶體。應用的dex code、heap以及執行時的記憶體分配都會在這塊記憶體中。而使用列舉型別的dex size是普通常亮的13倍以上。在執行時的記憶體分配,一個enum的宣告至少要消耗掉20個bytes。從這兩點就可以說明,在app中大量使用列舉的記憶體開銷是非常大的。

列舉最大的優勢是型別安全。那麼是不是又辦法在不使用列舉的情況下做到型別安全呢?答案是肯定的,下面看看怎麼幹。

goodle官方很早就發現了列舉對android系統帶來的效能開銷,所以在其官網上就已經提醒了開發者儘量少的使用列舉,而且還提供了註解的方式來檢查型別安全。目前其提供了int和string兩種註解方式。分別是:IntDef和StringDef。

話不多說,直接上例子。ps:demo裡面有詳細的註釋。

一、Int型別註解檢查型別安全

package com.yw.enumproxylib;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import androidx.annotation.IntDef;

/**
 * 定義一個int型別的註解
 * 用註解代替列舉,做到型別安全
 * create by yangwei
 * on 2020-01-30 21:34
 */
public class EnumProxy {
  public static final int READ_CAR = 0;//紅色的汽車
  public static final int GREEN_CAR = 1;//綠色的汽車
  public static final int YELLOW_CAR = 2;//黃色的汽車


  @IntDef({READ_CAR,GREEN_CAR,YELLOW_CAR})
  @Retention(RetentionPolicy.SOURCE)//原始碼級別
  public @interface CAR_Enum {

  }

  /**
   * 獲取汽車型別
   *
   * @param car
   * @return
   */
  public static int getCar(@CAR_Enum int car) {
    switch (car) {
      case READ_CAR:
        return 0;
      case GREEN_CAR:
        return 1;
      case YELLOW_CAR:
        return 2;
    }
    return -1;
  }
}

二、String型別註解檢查型別安全

package com.yw.enumproxylib;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import androidx.annotation.StringDef;

/**
 * 定義一個string型別的註解,用於檢查星期的型別安全。
 * create by yangwei
 * on 2020-01-30 22:04 week
 */
public class StringEnum {

  public static final String MONDAY = "monday";
  public static final String TUESDAY = "tuesday";
  public static final String WENDESDAY = "wendesday";
  public static final String THURSDAY = "thursday";
  public static final String FRIDAY = "friday";
  public static final String SATURDAY = "saturday";
  public static final String WEEKDAY = "weekday";

  @StringDef({MONDAY,TUESDAY,WENDESDAY,THURSDAY,FRIDAY,SATURDAY,WEEKDAY})//此處定義註解的值只能是這幾個
  @Retention(RetentionPolicy.SOURCE)//編譯時註解,原始碼級檢查
  public @interface Week {

  }

  /**
   * 獲取日期
   *
   * @param week
   * @return
   */
  public static String getWeek(@Week String week) {
    switch (week) {
      case MONDAY:
        return "星期一";
      case TUESDAY:
        return "星期二";
      case WENDESDAY:
        return "星期三";
      case THURSDAY:
        return "星期四";
      case FRIDAY:
        return "星期五";
      case SATURDAY:
        return "星期六";
      case WEEKDAY:
        return "星期日";
    }
    return null;
  }
}

三、用來檢查型別安全的MainActivity,從下面可以看到,當使用EnumProxy.getCar輸入引數的時候,如果直接輸入一個整數則編譯不通過。當輸入我們定義的EnumProxy.GREEN_CAR編譯才通過。

同理StringEnum也能檢查型別安全。

package com.yw.enumproxy;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.yw.enumproxylib.EnumProxy;
import com.yw.enumproxylib.StringEnum;

/**
 * 測試例子
 */
public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    int car_black = 10;
    int bk = EnumProxy.getCar(car_black);//此處型別檢查不通過
    int ck = EnumProxy.getCar(EnumProxy.GREEN_CAR);//型別檢查通過


    String str = "friday";
    String week1 = StringEnum.getWeek(str);//直接賦值String時型別檢查不通過
    String week2 = StringEnum.getWeek(StringEnum.FRIDAY);//賦值定義好的值時型別檢查通過
  }
}

以上知識點如果大家在學習的時候有任何疑問可以聯絡我們小編補充分享。