Scenario introduction
When the application enters the front desk from the background, it jumps to the start page to display the opening advertisement, which is a common scene. Often we need to add some control conditions, not all cases jump off the screen advertising, so the user experience is poor, so there will be a series of filtering conditions.
Initial scheme
At first it was like this:
- Determine whether masking is necessary to return from a page
- Judgment Channel
- Control interval time, number limit, etc. according to interface content
if (activity instanceof SplashActivity) { //Start Page return; } if (activity instanceof LockScreenActivity) { //Lock screen return; } if (activity instanceof AlcWidgetBaseConfigActivity) { //Component Settings return; } if(AlcChannelUtil.isHuawei(this)){ return; } String data = OnlineData.getInstance().getKey(activity, "go_splash_open", ""); int status = 0; int oneDayMaxCount = 5; //120 seconds 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; //Turn to milliseconds offsetTime = offsetTime * 1000; if (isOpen) { //If open long lastSplashTime = (long) SPUtils.get(activity, "lastSplashTime", 0L); //And the time interval is larger than the set time interval. if ((System.currentTimeMillis() - lastSplashTime) > offsetTime) { //Re-judge whether the number of times reached the upper limit //Judging whether it is today int todayOpenCount = 0; if (TimeUtils.isSameDay(lastSplashTime)) { todayOpenCount = (int) SPUtils.get(activity, "todayOpenCount", 0); } if (todayOpenCount < oneDayMaxCount) { //Less than this number, go to the opening page, save this time, update the number of unfolds today 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); } } }
Written in one place, the code is bloated, and the expansibility is poor. If conditions are added or deleted in the follow-up, it is not appropriate to modify directly here. So I think of using the responsibility chain model to reform it.
Improvement
Define basic classes
Firstly, three basic classes are defined, one is the interceptor interface, the other is Chain used to connect all interceptors in series, and the other is the object Bean handled by the interceptor.
public interface BaseSplashAdInterceptor { /** * Processing filtering, such as modifying whether to jump advertising, modifying the type of advertising, etc. * * @param adStatusBean */ void doProcess(SplashAdStatusBean adStatusBean); }
Chain class
public class SplashAdChain { private List<BaseSplashAdInterceptor> mChains; /** * Adding interceptors * @param interceptor * @return */ public SplashAdChain addInterceptor(BaseSplashAdInterceptor interceptor) { if (mChains == null) { mChains = new ArrayList<>(); } mChains.add(interceptor); return this; } /** * Handling Interception Operations * @param adStatusBean */ public void doProcess(SplashAdStatusBean adStatusBean) { if (mChains != null) { for (BaseSplashAdInterceptor interceptor : mChains) { interceptor.doProcess(adStatusBean); } } } }
Operating object class:
public class SplashAdStatusBean implements Serializable { /** * Do you want to jump start page ads? */ private boolean isNeedGoSplashAd; /** * Types of Advertising */ private int splashAdType; /** * Where did it come from? */ private Activity currentActivity; //... set and get methods, construction methods, etc. }
Setting up interceptors
Then the interceptor is set up according to some conditions, such as:
/** * Filtering Activity * * @author moore * @date 2019/8/5 */ public class SplashAdActivityInterceptor implements BaseSplashAdInterceptor { @Override public void doProcess(SplashAdStatusBean adStatusBean) { if (adStatusBean.isNeedGoSplashAd()) { //If you need to jump, filter again Activity currentActivity = adStatusBean.getCurrentActivity(); if (currentActivity == null) { adStatusBean.setNeedGoSplashAd(false); return; } if (currentActivity instanceof SplashActivity) { //Start Page adStatusBean.setNeedGoSplashAd(false); return; } if (currentActivity instanceof LockScreenActivity) { //Lock screen adStatusBean.setNeedGoSplashAd(false); return; } if (currentActivity instanceof AlcWidgetBaseConfigActivity) { //Component Settings adStatusBean.setNeedGoSplashAd(false); return; } } } }
The other conditions are the same. Move him into the interceptor to operate, classify and so on. Such as controlling time, controlling number of times, controlling type of advertisement and so on.
Use interceptors
After defining these conditions, you can use them and add them on demand. Finally, you will get an object that has been processed by each interceptor. According to some values in the object, you can proceed to the next step.
//Interception filtering without jumping start pages SplashAdStatusBean statusBean = new SplashAdStatusBean(true, 5, activity); SplashAdChain chain = new SplashAdChain() .addInterceptor(new SplashAdActivityInterceptor()) .addInterceptor(new SplashAdChannelInterceptor()) .addInterceptor(new SplashAdTimesInterceptor()); chain.doProcess(statusBean); //If you need to jump after interception, jump.~~~ 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); }
epilogue
Such partitioning will significantly increase the number of classes, but we can clearly see these filter interception operations, and future modifications will also be clearer, reducing code coupling.