背景

前几天看到秋百万的一篇文章Android 中的 Enum 到底占多少内存?该如何用?,其实对这个东西还是很敏感的,因为最近就在Android的项目中就用到了一个枚举类。不是不知道枚举的坏处,而是枚举具有很好的约束能力,所以才选择了它。

但是似乎在Android平台上其约束能力体现出来的优点还不足以抵消它的缺点,恰恰其带来的内存消耗牺牲更大。当然我是知道这一点的,但是并没有对具体的数值做过测试,因为之前认为这在一个可以接受的范围内。看了秋百万的文章后,即使觉得不碍大事,但是在Android里使用枚举是一个不好的习惯,毕竟Android不是Web,因此有必要重构一发代码。

枚举

首先来看看我这个枚举类是什么,这是一个涉及到http接口环境的类。这个类的大致内容如下。

public enum Environment {    /** * 正式环境http */    RELEASE_HTTP("http://gw.release.domain.com"),    /** * 预发环境http */    PRE_HTTP("http://gw.pre.domain.com"),    /** * 测试环境http */    DAILY_HTTP("http://gw.daily.domain.com"),    /** * 正式环境https */    RELEASE_HTTPS("https://gw.release.domain.com"),    /** * 预发环境https */    PRE_HTTPS("https://gw.pre.domain.com"),    /** * 测试环境https */    DAILY_HTTPS("https://gw.daily.domain.com");    /** * url */    String mEnvironmentHost;    /** * @param environmentHost */    Environment(String environmentHost) {        this.mEnvironmentHost = environmentHost;    }    //根据Environment获得url    public String getEnviromentHost() {        return mEnvironmentHost;    }    /** * 根据url返回Environment枚举类 * @param host * @return */    public static Environment fromHost(String host) {        for (Environment value : values()) {            if (value.getEnviromentHost().equals(host)) {                return value;            }        }        return null;    }}

之所以使用枚举类,是因为我想约束这个url为这个6个url中的其中一个,并不想让开发者传入这6个环境以外的其他任意一个环境。环境分为http和https,并且都具有日常,预发,线上三者,2*3=6,刚好6种。

真正使用时,直接使用枚举类限定参数类型,这样就起到了很好的约束能力。

private Environment environment;public void setEnvironment(Environment environment) {    this.environment = environment;}

其实在写这个类的时候,我再三考虑要不要使用枚举,但是最终我用了,因为我使用常量的话,就起不到这个约束能力了。

注解

之前看到Android源码中有使用注解进行约束,比如资源的约束就有这么一些注解:@ColorRes、@RawRes、@StringRes、@LayoutRes、@AnimatorRes、@AnimRes、@ArrayRes、@AttrRes、@BoolRes、@DimenRes、@DrawableRes、@IdRes等等。

其实看到过一段源码,是设置View的Visibility属性的。

public void setVisibility(@Visibility int visibility) {    setFlags(visibility, VISIBILITY_MASK);}

当时知道可以通过注解来约束这个参数,但是没有跟进去看这个注解到底是什么。其实这个注解用了另一个注解@IntDef,其作用就是让加上了@Visibility注解的参数约束为@IntDef中定义的数组的值,这里就是约束为了VISIBLE, INVISIBLE, GONE三个int常量

public static final int VISIBLE = 0x00000000;public static final int INVISIBLE = 0x00000004;public static final int GONE = 0x00000008;@IntDef({VISIBLE, INVISIBLE, GONE})@Retention(RetentionPolicy.SOURCE)public @interface Visibility {}

而这个@IntDef注解是在support-annotations包中。

compile 'com.android.support:support-annotations:23.3.0'}

除了@IntDef注解外,这个包中还有很多注解,作用其实都是为了起到一定程度的约束作用。

最佳实践

于是,我准备用该包中的注解进行对枚举类的改造。其实用到的就一个注解,即@StringDef注解。

首先建立一个@Environment注解,在里面定义6个字符串常量,即不同的环境。

public @interface Environment {    /** * 正式环境http */    public static final String RELEASE_HTTP = "http://gw.release.domain.com";    /** * 预发环境http */    public static final String PRE_HTTP = "http://gw.pre.domain.com";    /** * 测试环境http */    public static final String DAILY_HTTP = "http://gw.daily.domain.com";    /** * 正式环境https */    public static final String RELEASE_HTTPS = "https://gw.release.domain.com";    /** * 预发环境https */    public static final String PRE_HTTPS = "https://gw.pre.domain.com";    /** * 测试环境https */    public static final String DAILY_HTTPS = "https://gw.daily.domain.com";}

然后在该注解上加上@StringDef注解,约束为定义的6个常量

@StringDef({Environment.RELEASE_HTTP, Environment.PRE_HTTP, Environment.DAILY_HTTP, Environment.DAILY_HTTPS, Environment.PRE_HTTPS, Environment.RELEASE_HTTPS})

为了让注解只在源码级别存在,我们还需要加入下面的元注解

@Retention(RetentionPolicy.SOURCE)

最后就是修改设置环境的代码,在其入参上加入注解限制。

private String environment;public void setEnvironment(@Environment String environment) {    this.environment = environment;}

这时候,如果你使用的不是注解约束的6个环境,那么就会报一个提示,并且是红色的下划线,提示你这里需要修改。

于是你必须像这么使用

core.setEnvironment(Environment.DAILY_HTTP);core.setEnvironment(Environment.PRE_HTTP);core.setEnvironment(Environment.RELEASE_HTTP);core.setEnvironment(Environment.DAILY_HTTPS);core.setEnvironment(Environment.PRE_HTTPS);core.setEnvironment(Environment.RELEASE_HTTPS); 

这样以来,在一定程度上能起到约束作用。But,如果你无视了该警告,编译仍然是可以通过的哟~,这一点需要特别注意哦。

其实这个support-annotation包中还有很多很有用的注解,有兴趣的可以自己一一去看一下。

更多相关文章

  1. Android(安卓)Metro风格的Launcher开发系列第一篇
  2. android/c++ opencv 攻坚篇(一) ndk运行环境搭建
  3. android sdk myeclipse8.6
  4. Android(安卓)环境搭建,Helloworld以及常见错误处理,最新版哦
  5. 2013年01月小记
  6. Android(安卓)项目导入后真机运行提示:W/dalvikvm(10375): VFY 错
  7. 开发环境之Mac上Android(安卓)Studio上虚拟AVD设备不显示
  8. 【MonkeyRunner】eclipse中编写monkeyrunner脚本环境搭建
  9. 【Android(安卓)Native Code开发系列】三 Android源码的编译环境

随机推荐

  1. 分析PHP错误处理(核心特性)
  2. PHP操作Redis数据库常用方法(总结)
  3. PHP使用redis作为缓存(高效技术)
  4. php性能优化的方法介绍
  5. php实现顺序线性表
  6. Kubernetes 如果是个水族馆
  7. 自学系列 | 就谈自我管理!
  8. 智慧城市信息安全探讨
  9. 1-22
  10. 动画:面试必刷之二叉树的子结构