使用枚举管理不同渠道版本常量

发布于:

编程

工作中遇到了需要根据不同渠道配置不同广告 ID 需求,而且渠道很多,变动可能很频繁,如何才能高效配置管理呢?通过思考实践,我最终使用了枚举来管理不同渠道的广告 ID。

一般的字符串常量

在项目刚开始时,是没有根据不同渠道使用不同广告位ID的需求的,最初只是使用了简单的字符串常量来保存这些初始化数据。

public final static String APP_ID = "54513248";  
  
public final static String UM_ID = "RANDOM8TN2zx0QlLRfsXGRNU";  
public final static String UM_CHANNEL = "Umeng";  
  
public final static String SPLASH_AD_ID = "****";  
public final static String INTERACTION_AD_ID = "****";  
public final static String VIDEO_AD_ID = "****";  
public final static String BANNER_AD_ID = "****";  
public final static String FEED_AD_ID = "****";  
  
public final static String PROFILE_BANNER_AD_ID = "****";  
  
public final static String SCRATCH_REWARD_AD_ID = "****";  
public final static String SCRATCH_BANNER_AD_ID = "****";

进化为枚举管理

在收到不同渠道不同广告位ID的需求后,首先考虑到便于编译,不能通过简单的更改和注释的方法来管理字符串常量,这样每次渠道编译都要修改,很麻烦。如果使用 flavor 直接填充变量,数据太多不宜在 build.gradle 中维护,扩展性也不好。

也考虑了使用 xml 中配置 strings-arrays 字符串配置,想想要调整不同的文件,还要引入到上下文加载,也不是一个好的选择。

再次想到了使用 interface来定义一个基类,返回实现不同的渠道实例来填充广告位ID,实现下来代码也很繁琐,有些过渡设计。而考虑到 Enum 是单实例 Class 的本质,想法自然向枚举靠拢。

1. 定义常量

首先在枚举中定义常量的列表

@Keep  
public enum AdsIds {  
    public String APP_ID = "54513248";  
  
    public String UM_ID = "RANDOM8TN2zx0QlLRfsXGRNU";  
    public String UM_CHANNEL = "Umeng";  
  
    public String SPLASH_AD_ID;  
    public String INTERACTION_AD_ID;  
    public String VIDEO_AD_ID;  
    public String BANNER_AD_ID;  
    public String FEED_AD_ID;  
  
    public String PROFILE_BANNER_AD_ID;  
  
    public String SCRATCH_REWARD_AD_ID;  
    public String SCRATCH_BANNER_AD_ID;   
}

2. 增加枚举实例内初始化

要在每个枚举实例内初始化数据,需要增加一个 init() 抽象方法,同时在枚举的构造方法中调用这个 init() 方法。

public enum AdsIds { 
  ...
   AdsIds() {  
        init();  
    }  
    protected abstract void init(); 
    ...
}

3. 增加枚举实例

这时就可以为每个渠道增加枚举实例并初始化常量了:

public enum AdsIds { 
    COMMON {  
        @Override  
        protected void init() {  
            SPLASH_AD_ID = "814272";  
            INTERACTION_AD_ID = "817562";  
            VIDEO_AD_ID = "815884";  
            BANNER_AD_ID = "889664";  
            FEED_AD_ID = "844311";  
      
            PROFILE_BANNER_AD_ID = "808569";  
      
            SCRATCH_REWARD_AD_ID = "815990";  
            SCRATCH_BANNER_AD_ID = "892691";  
        }  
    },  
      
    CHANNEL_A {  
        @Override  
        protected void init() {  
            UM_CHANNEL = "CHANNEL_1";  
  
            SPLASH_AD_ID = "812097";  
            INTERACTION_AD_ID = "814895";  
            VIDEO_AD_ID = "877058";  
            BANNER_AD_ID = "879158";  
            FEED_AD_ID = "896762";  
      
            PROFILE_BANNER_AD_ID = "832216";  
        }  
    },
    ...
    ;
}

注意最后一个枚举的结尾是分号;,如果需要再增加不同渠道,只需要再增加一个新的枚举实例就可以了。

4. 代码调用

public class Constants {  
    public static AdsIds IDS = AdsIds.COMMON;
}

使用

adsHolder.setAdId(Constants.IDS.BANNER_AD_ID);

语句调用即可。

为了配合 flavor 控制,可以在 Constants 中增加一个 CHANNEL 的常量,这部分只做示例,读者可以自己讨论扩展:

@Keep  
public class Constants {  
  
    // Change this, use flavor to control CHANNEL...
    public static final Channel CHANNEL = Channel.COMMON;    
    public static AdsIds IDS = AdsIds.valueOf(CHANNEL.name());
}

public enum Channel {  
    COMMON,  
    EXTERNAL,  
    PLAY_STORE,  
    CHANNEL_A  
}

完整代码示例

最终的实现简单明了,配置维护方便,代码如下:

@Keep  
public enum AdsIds {  
    COMMON {  
        @Override  
        protected void init() {  
            SPLASH_AD_ID = "814272";  
            INTERACTION_AD_ID = "817562";  
            VIDEO_AD_ID = "815884";  
            BANNER_AD_ID = "889664";  
            FEED_AD_ID = "844311";  
  
            PROFILE_BANNER_AD_ID = "808569";  
  
            SCRATCH_REWARD_AD_ID = "815990";  
            SCRATCH_BANNER_AD_ID = "892691";  
        }  
    },  
  
    CHANNEL_A {  
        @Override  
        protected void init() {  
            UM_CHANNEL = "CHANNEL_1";  
  
            SPLASH_AD_ID = "812097";  
            INTERACTION_AD_ID = "814895";  
            VIDEO_AD_ID = "877058";  
            BANNER_AD_ID = "879158";  
            FEED_AD_ID = "896762";  
  
            PROFILE_BANNER_AD_ID = "832216";  
        }  
    },  
  
  
    EXTERNAL {  
        @Override  
        protected void init() {  
            SPLASH_AD_ID = "845812";  
            INTERACTION_AD_ID = "870659";  
            VIDEO_AD_ID = "893231";  
            BANNER_AD_ID = "851338";  
            FEED_AD_ID = "847696";  
  
            PROFILE_BANNER_AD_ID = "895238";  
  
            SCRATCH_REWARD_AD_ID = "840528";  
            SCRATCH_BANNER_AD_ID = "865717";  
        }  
    },  
  
    PLAY_STORE {  
        @Override  
        protected void init() {  
            UM_CHANNEL = "PLAY_STORE";  
            SPLASH_AD_ID = "868959";  
            INTERACTION_AD_ID = "874990";  
            VIDEO_AD_ID = "875137";  
            BANNER_AD_ID = "866426";  
            FEED_AD_ID = "839792";  
  
            PROFILE_BANNER_AD_ID = "864501";  
  
  
            SCRATCH_REWARD_AD_ID = "897767";  
            SCRATCH_BANNER_AD_ID = "863937";  
        }  
    };  
  
    public String APP_ID = "54513248";  
  
    public String UM_ID = "RANDOM8TN2zx0QlLRfsXGRNU";  
    public String UM_CHANNEL = "Umeng";  
  
    public String SPLASH_AD_ID;  
    public String INTERACTION_AD_ID;  
    public String VIDEO_AD_ID;  
    public String BANNER_AD_ID;  
    public String FEED_AD_ID;  
  
    public String PROFILE_BANNER_AD_ID;  
  
    public String SCRATCH_REWARD_AD_ID;  
    public String SCRATCH_BANNER_AD_ID;  
  
    AdsIds() {  
        init();  
    }  
  
    protected abstract void init();  
}

上文代码中的 ID 和 Key 都是随机字符串,没有绑定到特定的应用信息。