Android中使用注解替代枚举

2018-05-08  本文已影响26人  珊珊宝贝Catherine

枚举最大的作用是提供了类型安全。为了弥补Android平台不建议使用枚举的缺陷,官方推出了两个注解,IntDef和StringDef,用来提供编译期的类型检查。
首先,引入依赖包:

implementation 'com.android.support:support-annotations:27.1.0'

定义一个注解

public @interface TaskStatus {

}

是的,类似于接口的定义,加个 @ 符号。

注解一般使用步骤

那么对于上面的枚举和常量都不 work 的场景,如何使用枚举解决呢?

  1. 定义注解类,添加常量
@Retention(RetentionPolicy.SOURCE)
public @interface TaskStatus {
    int UN_KNOW = -1;
    int UN_START = 0;
    int PROGRESSING = 1;
    int COMPLETED = 2;
}

和接口成员一样,注解类的成员默认就是 public static final 修饰的。

@Retention(RetentionPolicy.SOURCE) 表示告诉编译器,该注解是源代码级别的,生成 class 文件的时候这个注解就被编译器自动去掉了。

doSth() 方法:

public class TaskHelper {

    public static void doSth(@TaskStatus int status){
        switch (status){
            case TaskStatus.UN_KNOW:
                //do something
                break;
            case TaskStatus.UN_START:
                break;
            case TaskStatus.PROGRESSING:
                break;
            case TaskStatus.COMPLETED:
                break;
        }
    }
}

可以看出,doSth() 方法的参数是 int 类型的,但是使用 @TaskStatus 进行了注解,这样外界就无法传递 TaskStatus之外的成员作为参数了。

  1. 调用
TaskHelper.doSth(TaskStatus.UN_START);

在调用时,IDE 会提示 @TaskStatus int status,提醒我们传入 TaskStatus 类型的值。

同时,调用者如果再随便传入一个 int 值,虽然可以运行,但代码会爆红,lint 检查将会给与警告:

Must be one of: TaskStatus.UN_KNOW, TaskStatus.UN_START, TaskStatus.PROGRESSING, TaskStatus.COMPLETED

如此,保证了类型安全。但也只是警告,仍然可以运行,但总比没有警告强多了。

补充

其实这种用法在 Android 源码中屡见不鲜,比如 Resources 下的 getDrawable() 方法:

public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
        final Drawable d = getDrawable(id, null);
        //...
        return d;
    }

使用时,我们一般会这么用:

getResources().getDrawable(R.drawable.ic_launcher);

虽然是 int 值,但是当我们这么用时:

getResources().getDrawable(111);

就会爆红并提示:

Expected resource of type drawable

再补充一点,为了防止在我们定义的常量值重复,我们还可以使用Android 注解支持库(support-annotations)中的 @IntDef 来限定常量不允许重复:

@IntDef({
        TaskStatus.UN_KNOW,
        TaskStatus.UN_START,
        TaskStatus.PROGRESSING,
        TaskStatus.COMPLETED
})
@Retention(RetentionPolicy.SOURCE)
public @interface TaskStatus {
    int UN_KNOW = -1;
    int UN_START = 0;
    int PROGRESSING = 1;
    int COMPLETED = 2;
}
上一篇下一篇

猜你喜欢

热点阅读