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);//賦值定義好的值時類型檢查通過
    }
}

 

結束語:github上demo地址,有興趣的可以下載下來看看:https://github.com/ywtony/enumproxy

。疫情期間大家不要亂跑,出門記得戴口罩。中國加油、武漢加油。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM