Android 枚举类型

本文介绍了在Android开发中如何利用枚举类型进行高效且安全的编程实践,包括枚举的基本用法、实现单例模式、自定义属性及方法等,并探讨了枚举类型的内存占用情况。同时,还介绍了Android官方推荐的使用注解来增强枚举类型的可维护性和可读性。

业务场景:

有些时候我们有一排相同类型的东西需要展示,当时每个子项可能包含具体的id。名称,简介。为了方便管理和修改。我们把它放在枚举类型中,方便管理。

Android enum

1)替换场景

   通过enum关键字来实现枚举,在枚举中需要注意的有:

        1. 枚举中的属性必须放在最前面,一般使用大写字母表示

        2. 枚举中可以和java类一样定义方法

        3. 枚举中的构造方法必须是私有的

        4.可以在枚举属性后面添加()来调用指定参数的构造方法,添加{}来实现其对应的匿名内部类

                   RED(30){ public TrafficLamp nextLamp() { return GREEN ; } }

原:

    public static final int COLOR_RED = 0;
    public static final int COLOR_GREEN =1;
    public static final int COLOR_BLUE = 2;

替换后:

public enum ColorEnum{
    RED,
    GREEN,
    YELLOW
}

使用枚举类型可以提高代码的安全性(防止输入枚举之外的值)和可读性(在打印日志时)。另外注意两个点:上述的ColorEnum实质上会在编译时转换成继承java.lang.enum的类,所以ColorEnum不可继承自其它的类。此外,被编译后的ColorEnum会被标记为final,即不可被继承

2)枚举类型实现单例

public enum NetworkManager {

    instance;

          xxxxx

}

使用 

NetworkManager.instance.xxxx

enum 对象的常用方法介绍:

 

int compareTo(E o) 
          比较此枚举与指定对象的顺序。

Class<E> getDeclaringClass() 
          返回与此枚举常量的枚举类型相对应的 Class 对象。

String name() 
          返回此枚举常量的名称,在其枚举声明中对其进行声明。

int ordinal() 
          返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

String toString()
          返回枚举常量的名称,它包含在声明中。

static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) 
          返回带指定名称的指定枚举类型的枚举常量

给 enum 对象加一下 value 的属性和 getValue() 的方法:


   MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6) ,
    SUN(0) {
        @Override
        public boolean isRest() {
            return true;
        }
    };
 
    private int value;
 
    private EnumTest(int value) {
        this.value = value;
    }
 
    public int getValue() {
        return value;

   }

。。。。

可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)

Android 中的 Enum 到底占多少内存?该如何用?

占用了很大的 dex 文件,占用很多内存

假设有 n 个枚举值,仅仅考虑枚举类,静态占用的内存,n 个引用 + n 个数组 + 24 空数组长度: 8n + 24。

而对于 n 个值的常量,则有 4n 字节。当 n 很大时,这样的关系是两倍,但是枚举引用所指向的内存(retained heap)没有考虑进来。

Android中使用枚举的正确姿势

Android官方引入了两个注解,分别是StringDef和IntDef。具体方法见下:
首先引入依赖:
compile 'com.android.support:support-annotations:25.1.0'

public interface ISearchTypeClickListener {

    @IntDef({Type.hot, Type.recommend, Type.result, Type.history})

    @Retention(RetentionPolicy.SOURCE)
    @interface Type {
        int hot = 0x110;
        int recommend = 0x111;
        int result = 0x112;
        int history = 0x113;
    }

    void itemClick(@Type int fromType, int position, Program program);

}

 

注解生命周期

  • RetentionPolicy.SOURCE 源码注解,编译成.class文件后注解就不存在,用来提示开发者
  • RetentionPolicy.CLASS CLASS汇编注解,编译成.class文件后注解也还存在,用于自动生成代码
  • RetentionPolicy.RUNTIME 运行时动态注解,生命周期一直程序运行时都存在,常用于自动注入

 


 

 

 
<think>我们正在讨论在Android中使用Bundle传递枚举类型的方法。根据引用[1][2][3]的内容,传递枚举类型的关键在于枚举实现了Serializable接口,因此可以通过Bundle的putSerializable方法存储,并通过getSerializable方法获取。 ### 具体步骤: 1. **存储枚举到Bundle**:使用`bundle.putSerializable(key, enumValue)`,其中`enumValue`是枚举实例。 2. **从Bundle获取枚举**:使用`(EnumType) bundle.getSerializable(key)`,注意进行强制类型转换。 ### 代码示例: 假设我们有一个枚举类型`FRUITS`: ```java public enum FRUITS { APPLE, ORANGE, BANANA } ``` #### 传递枚举: ```java // 在Activity或Fragment中 Intent intent = new Intent(this, TargetActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("fruit_key", FRUITS.APPLE); // 存储枚举 intent.putExtras(bundle); startActivity(intent); ``` #### 接收枚举: ```java // 在目标Activity的onCreate中 Bundle bundle = getIntent().getExtras(); if (bundle != null) { FRUITS fruit = (FRUITS) bundle.getSerializable("fruit_key"); // 获取并转换枚举 // 使用枚举 } ``` ### 注意事项: 1. **枚举类必须实现Serializable**:Java枚举默认实现Serializable,因此无需额外实现。 2. **键名一致**:存储和提取时使用相同的键。 3. **空值检查**:确保Bundle不为空,避免NullPointerException。 ### 替代方案(不推荐): 虽然枚举可序列化,但大量使用可能影响性能(每个枚举值都是一个对象)。替代方案包括: - 使用字符串或整型常量传递,接收端再转换回枚举(如`FRUITS.valueOf(string)`)。 - 对于复杂场景,考虑使用Parcelable,但枚举本身不支持Parcelable,需手动封装。 ### 结论: **推荐使用`putSerializable`和`getSerializable`传递枚举**,这是Android中处理枚举类型最直接的方式[^1][^2][^3]。 §§相关问题§§ 1. 如何在Fragment之间传递枚举类型? 2. 传递枚举与传递字符串常量相比有何优缺点? 3. 如何安全地处理Bundle中可能不存在的枚举键? **注意**:以上回答基于提供的引用内容,实际开发中应确保枚举类在发送和接收端均可访问(同包或public修饰)。 </think> # Android中使用Bundle传递枚举类型的完整指南 在Android开发中,通过Bundle传递枚举类型是常见需求。以下是基于Java和Kotlin的实现方法: ## 核心原理 枚举类型默认实现了`Serializable`接口,因此可以通过Bundle的`putSerializable()`和`getSerializable()`方法传递[^1][^2]。 ### 枚举定义示例 ```java // Java public enum FruitType { APPLE, ORANGE, BANANA } ``` ```kotlin // Kotlin enum class FruitType { APPLE, ORANGE, BANANA } ``` ## Java实现方法 ### 1. 存储枚举到Bundle ```java Intent intent = new Intent(this, TargetActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("fruit_key", FruitType.APPLE); // 存储枚举 intent.putExtras(bundle); startActivity(intent); ``` ### 2. 从Bundle获取枚举 ```java Bundle bundle = getIntent().getExtras(); if (bundle != null) { FruitType fruit = (FruitType) bundle.getSerializable("fruit_key"); // 使用枚举值 if (fruit == FruitType.APPLE) { // 处理苹果类型 } } ``` ## Kotlin实现方法 ### 1. 存储枚举到Bundle ```kotlin val intent = Intent(this, TargetActivity::class.java) val bundle = Bundle().apply { putSerializable("fruit_key", FruitType.ORANGE) } intent.putExtras(bundle) startActivity(intent) ``` ### 2. 从Bundle获取枚举(安全方式) ```kotlin val bundle: Bundle? = intent.extras val fruit = bundle?.getSerializable("fruit_key") as? FruitType when (fruit) { FruitType.APPLE -> handleApple() FruitType.ORANGE -> handleOrange() FruitType.BANANA -> handleBanana() null -> handleMissingValue() // 处理空值情况 } ``` ## 最佳实践与注意事项 1. **键名管理**:使用常量定义键名避免拼写错误 ```java public static final String KEY_FRUIT_TYPE = "fruit_type"; ``` 2. **空值处理**:总是检查Bundle是否为空 ```java if (bundle != null && bundle.containsKey(KEY_FRUIT_TYPE)) { // 安全获取值 } ``` 3. **类型安全转换**:在Kotlin中使用`as?`进行安全类型转换 4. **复杂枚举处理**:对于带参数的枚举 ```java public enum Status { SUCCESS(200), ERROR(500); private final int code; Status(int code) { this.code = code; } public int getCode() { return code; } } ``` ## 替代方案比较 | 方法 | 优点 | 缺点 | |------|------|------| | **Serializable** | 简单直接,无需额外代码 | 性能较低,反射开销 | | **Parcelable** | 高性能,Android专用 | 需要实现Parcelable接口 | | **字符串转换** | 轻量,可读性好 | 需要手动转换,易出错 | ### Parcelable实现示例(高性能替代) ```java public enum FruitType implements Parcelable { // ... 枚举值 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(ordinal()); } public static final Creator<FruitType> CREATOR = new Creator<FruitType>() { @Override public FruitType createFromParcel(Parcel in) { return FruitType.values()[in.readInt()]; } @Override public FruitType[] newArray(int size) { return new FruitType[size]; } }; } ``` ## 常见问题解决 **Q: 为什么传递枚举时出现ClassCastException?** A: 确保发送端和接收端的枚举类全路径完全相同(包名+类名) **Q: 如何传递枚举集合?** ```java ArrayList<FruitType> fruits = new ArrayList<>(); bundle.putSerializable("fruits_list", fruits); ``` **Q: 枚举传递的性能影响?** A: 对于高频传递场景,考虑使用Parcelable或整型值替代 通过以上方法,您可以安全高效地在Android组件间传递枚举类型数据[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值