场景介绍
应用从后台进入前台的时候,跳转到启动页进行开屏广告的展示,比较常见的一种场景了。往往我们需要加上一些控制条件,不是所有的情况都跳开屏广告,那样用户体验就差了,所以就会有一系列过滤条件。
初始方案
最开始是这样的:
- 判断是否需要屏蔽从某一个页面回来
- 判断渠道
- 根据接口内容控制间隔时间、次数限制等
if (activity instanceof SplashActivity) {
//启动页
return;
}
if (activity instanceof LockScreenActivity) {
//锁屏
return;
}
if (activity instanceof AlcWidgetBaseConfigActivity) {
//组件设置
return;
}
if(AlcChannelUtil.isHuawei(this)){
return;
}
String data = OnlineData.getInstance().getKey(activity, "go_splash_open", "");
int status = 0;
int oneDayMaxCount = 5;
//120秒
int offsetTime = 60;
if (!TextUtils.isEmpty(data)) {
try {
JSONObject object = new JSONObject(data);
status = object.optInt("isOpen");
offsetTime = object.optInt("offsetTime");
oneDayMaxCount = object.optInt("oneDayMaxCount");
} catch (JSONException e) {
e.printStackTrace();
}
}
boolean isOpen = status == 1;
//转成毫秒
offsetTime = offsetTime * 1000;
if (isOpen) {
//如果打开
long lastSplashTime = (long) SPUtils.get(activity, "lastSplashTime", 0L);
//并且时间间隔大于设置的时间间隔
if ((System.currentTimeMillis() - lastSplashTime) > offsetTime) {
//再判断次数是否达到上限
//判断是否是今天
int todayOpenCount = 0;
if (TimeUtils.isSameDay(lastSplashTime)) {
todayOpenCount = (int) SPUtils.get(activity, "todayOpenCount", 0);
}
if (todayOpenCount < oneDayMaxCount) {
//小于这个次数,进入开屏页,保存这一次的时间,更新今天展开次数
SPUtils.put(activity, "lastSplashTime", System.currentTimeMillis());
todayOpenCount++;
SPUtils.put(activity, "todayOpenCount", todayOpenCount);
Intent goSplash = new Intent(activity, SplashActivity.class);
goSplash.putExtra("isFromOtherApp", true);
activity.startActivity(goSplash);
}
}
}
统统写在一个地方,代码臃肿,而且拓展性也差,后续如果加条件或者删条件,都是直接这里修改,感觉不太合适,于是想到用责任链模式进行改造一下。
改进
定义基本类
先定义三个基本类,一个是拦截器接口,一个是Chain用来串联所有拦截器,一个是拦截器处理的对象Bean。
public interface BaseSplashAdInterceptor {
/**
* 进行处理过滤,比如修改是否跳转广告、修改广告类型等
*
* @param adStatusBean
*/
void doProcess(SplashAdStatusBean adStatusBean);
}
Chain类
public class SplashAdChain {
private List<BaseSplashAdInterceptor> mChains;
/**
* 添加拦截器
* @param interceptor
* @return
*/
public SplashAdChain addInterceptor(BaseSplashAdInterceptor interceptor) {
if (mChains == null) {
mChains = new ArrayList<>();
}
mChains.add(interceptor);
return this;
}
/**
* 处理拦截操作
* @param adStatusBean
*/
public void doProcess(SplashAdStatusBean adStatusBean) {
if (mChains != null) {
for (BaseSplashAdInterceptor interceptor : mChains) {
interceptor.doProcess(adStatusBean);
}
}
}
}
操作对象类:
public class SplashAdStatusBean implements Serializable {
/**
* 是否要跳转启动页广告
*/
private boolean isNeedGoSplashAd;
/**
* 广告类型
*/
private int splashAdType;
/**
* 从哪里来的
*/
private Activity currentActivity;
//...set和get方法 ,构造方法等
}
设置拦截器
然后就是根据需要的一些条件进行设置拦截器了,例如:
/**
* 过滤Activity
*
* @author moore
* @date 2019/8/5
*/
public class SplashAdActivityInterceptor implements BaseSplashAdInterceptor {
@Override
public void doProcess(SplashAdStatusBean adStatusBean) {
if (adStatusBean.isNeedGoSplashAd()) {
//如果需要跳转,再进行过滤
Activity currentActivity = adStatusBean.getCurrentActivity();
if (currentActivity == null) {
adStatusBean.setNeedGoSplashAd(false);
return;
}
if (currentActivity instanceof SplashActivity) {
//启动页
adStatusBean.setNeedGoSplashAd(false);
return;
}
if (currentActivity instanceof LockScreenActivity) {
//锁屏
adStatusBean.setNeedGoSplashAd(false);
return;
}
if (currentActivity instanceof AlcWidgetBaseConfigActivity) {
//组件设置
adStatusBean.setNeedGoSplashAd(false);
return;
}
}
}
}
其他的条件也一样,把他搬到拦截器里去进行操作,分门别类之类的。像控制时间、控制次数、控制广告类型等等。
使用拦截器
定义好了这些条件之后,就可以使用了,按需添加,最后会得到一个经过各个拦截器处理过后的对象,根据这个对象里的一些值,进行下一步处理啦。
//拦截过滤不需要跳转启动页的情况
SplashAdStatusBean statusBean = new SplashAdStatusBean(true, 5, activity);
SplashAdChain chain = new SplashAdChain()
.addInterceptor(new SplashAdActivityInterceptor())
.addInterceptor(new SplashAdChannelInterceptor())
.addInterceptor(new SplashAdTimesInterceptor());
chain.doProcess(statusBean);
//拦截后如果需要跳转,那就跳转吧~~~
if (statusBean.isNeedGoSplashAd()) {
SPUtils.put(activity, "lastSplashTime", System.currentTimeMillis());
SPUtils.put(activity, "todayOpenCount", (statusBean.getTodayOpenCount() + 1));
Intent goSplash = new Intent(activity, SplashActivity.class);
goSplash.putExtra("isFromOtherApp", true);
activity.startActivity(goSplash);
}
结语
如此分割的话,会明显地增加类的数量,但是我们能比较清晰地看到这些过滤拦截操作,未来进行修改的时候也能更加清晰,降低代码耦合性。
网友评论