编程 3

Android全能拦截器Interceptor,缓冲动画以及页面跳转为1体的事例

By admin in 编程 on 2019年5月7日

这是2个应用js实现登入、缓冲动画以及页面跳转的例证。不要求用到数据库、没有供给复杂的逻辑、更不需求千行的代码;只供给多少个大致的竹签、几张GIF格式的图片、再增多几行代码就能够促成上述效用。本文首要有四个HTML页面构成,1个签到页面、多个加载缓冲页面、最终一个是缓冲过后的首页。为了做那么些GIF图,随即在英特网下了八个软件,轻易暴虐了点,虽有瑕疵,幸而麻雀虽小,伍脏俱全。笔者先把功效图先呈上。

一.概述

Interceptor拦截器,当大家在做多个体系的时候,会有众多亟需再行利用的方式依旧效用,当然,我们一般做的是包裹,恐怕在基类里面完结,然后子类基础,就防止了不计其数再度的操作,可是有时,这个也不是很轻便,依旧必要做一些附加的代码操作,比如,登入失效,须要跳到登入页面重新登陆的时候,有成都百货上千页面都有其1必要,一个个的去贯彻,又太费事,扩张不少不须求的代码,还有当项目繁多页面须要固定效能的时候,又得重新的写,像那种须求的时候,大家就足以用到拦截器了,基于Java声明的样式来使用。

编程,先看五个人逛窑子
首先个带了名流致薄的

编程 1

GIF.gif

第三个没带巅峰一号的

编程 2

GIF.gif

编程 3

贰.基类的概念和思维

  1. BaseApplication

/**
 * Created by asus on 2017/1/1.
 * Application基类,子类添加自己的拦截器
 */

public abstract class BaseApplication extends Application {
    private static Interceptors interceptors = new Interceptors();
    @Override
    public void onCreate() {
        super.onCreate();
        configInterceptor(interceptors);
    }

    public static final Interceptors getInterceptors() {
        return interceptors;
    }
    //子类实现的方法,添加自己的拦截器数组
    public abstract void configInterceptor(Interceptors interceptors);
}

2.BaseActivity

public class BaseActivity extends AppCompatActivity implements IVew {
    BaseApplication application;
    //子类实现禁止onCreate方法
    @Override
    protected final void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        application = (BaseApplication) getApplication();
        onInitView(savedInstanceState);
    }

    //禁止子类的onResume方法 并配置拦截器
    @Override
    protected final void onResume() {
        super.onResume();
        Interceptor[] globalInters = InterceptorBuilder.NULL_INTERS;
        Interceptors interceptors = application.getInterceptors();//获取拦截器集合
        if (interceptors != null) {
            globalInters = interceptors.getInterceptorArray();
        }
        Interceptor[] finalInters = InterceptorBuilder.build(globalInters, getClass());


        new Invocation(this, finalInters).invoke();
    }

    //子类获取对象
    @Override
    public Activity getViewActivity() {
        return this;
    }
    //设置主题
    @Override
    public void setWindowTheme() {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
    @Override
    public void onInitView(Bundle savedInstanceState) {

    }
    @Override
    public void resume() {

    }
}

三.VIew接口,便于完成部分操作,举例禁止子类的onCreate等方法,使用接口的主意

/**
 * Created by asus on 2017/1/1.
 *
 * 为了方便其他地方的调用采用接口的形式
 */

public interface IVew {

    //获取子类的对象
    Activity getViewActivity();

    //设置窗口样式  会在onCreate之前调用
    void setWindowTheme();

     //初始化控件;子类不能重写onCreate
    void onInitView(Bundle savedInstanceState);

    //视图可见;子类不能重写onResume
    void resume();
}

肆.每一个用到的拦截器数组

final public class Interceptors {

    private final List<Interceptor> globalActionInterceptor = new ArrayList<>();
      //添加一个初始化全局拦截器(例如定位,登录等,可以初始化全局)
    public Interceptors add(Interceptor globalInterceptor) {
        if (globalInterceptor != null)
            this.globalActionInterceptor.add(globalInterceptor);
        return this;
    }
    //获取当前应用所有的拦截器
    public Interceptor[] getInterceptorArray() {
        Interceptor[] result = globalActionInterceptor.toArray(new Interceptor[globalActionInterceptor.size()]);
        return result == null ? new Interceptor[0] : result;
    }
}
1、登录界面的HTML,一个账号和一个密码框,再加上两个按钮,结构如下:

<body>
    <div style="height:150px;width:250px;border:1px solid gray;margin:0 auto;padding-left:10px;">
        <p>
            <label>账号:</label>
            <input id="userName" placeholder="请输入用户名" type="text" name="name" value="" />
        </p>
        <p>
            <label>密码:</label>
            <input id="userPwd" placeholder="请输入密码" type="password" name="name" value="" />
        </p>
        <p>
            <input id="login" type="button" name="name" value="登录" style="margin-left:80px;" />
            <input id="close" type="button" name="name" value="取消" />
        </p>
    </div>


    <!--js部分-->
    <script>
        $("#login").click(function () {
            var userName = document.getElementById("userName").value;  //js获取input框中的值,用value
            var userPwd = document.getElementById("userPwd").value;
            //验证账号和密码
            if (userName == "wdk" && userPwd == "123456") {
                window.location.href = "/donghua.html";
            }
            else {
                alert("用户名或密码错误!");
                return;
            }
        })
    </script>
</body>

2、缓冲界面的HTML,主要就是一张GIF图片,当然,根据个人爱好你可以加上一些其他的配饰。结构如下:

<body>
    <div style="height:300px;width:300px;margin:0 auto;">
        <div id="time01">5</div>
        <img src="images/catBall.gif" />
        <h3>拼命加载中,请稍后……</h3>
    </div>

    <!--js部分-->
    <script>
        var t = 5;//自定义时间为5秒
        setInterval("jishi()", 1000); //定时器,每间隔1秒钟调用一次函数
        function jishi() {
            if (t==1) {
                location = '/shouye.html';  //缓冲完成后,页面跳转到首页
            }
            t--; //自减,实现倒计时
            document.getElementById("time01").innerHTML = t + "秒后进入首页";
        };
    </script>
</body>

3、首页的HTML,我们命名为shouye.html,就是缓冲完成后自动进入首页。在此页面,你可以自己写自己需要的代码了。结构如下:

<body>
    <div style="height:300px;width:300px;margin:0 auto;">
        <h3>这里是首页的界面</h3>
     在这个页面开始写你自己的代码 
        <img src="images/jiafeimao.gif" />
    </div>
</body>

后记:在很多的网页中,页面跳转之间都是用一张或多张图片甚至是视频来实现的,当然也有其他方式。本文的缓冲效果就是用了一张GIF格式的图片外加一个定时器来实现的,内容功能不多,但从登录到进入首页,也算是有头有尾了,对于有需要的朋友希望能从中找到借鉴之处,对于内容的缺陷或错误,也欢迎大家来批评和指教。

三.拦截器的定义

1.概念一个拦截器接口Interceptor

public interface Interceptor {
//并传入一个拦截器的拦截方法,做一些拦截判断操作
    void intercept(Invocation invocation);
}

贰.拦截器调解Invocation

/**
 * 拦截器调度
 * Created by asus on 2017/1/1.
 */

public class Invocation {
    private IVew view;
    private Interceptor[] inters;
    private int index = 0;

    public Invocation(IVew view, Interceptor[] interceptors) {
        this.view = view;
        this.inters = interceptors;
    }

    public void invoke(){
          //如果拦截器数组有值,则回调当前拦截器的操作
        if(index<inters.length){
            inters[index++].intercept(this);
//当当前拦截器执行完之后,又调用invoke方法,执行下一个拦截器,如果还有下一个拦截器,  
//继续执行intercept,否则才去回调当前activity的resume方法
        }else if(index++==inters.length){
            view.resume();
        }
    }
    public IVew getView() {
        return view;
    }
}

叁.概念自个儿的拦截器(作者这里是伪代码登入拦截器)

public class LoginInterceptor implements Interceptor {

    @Override
    public void intercept(Invocation inv) {
        Activity viewActivity = inv.getView().getViewActivity();
        //如果登录了继续回调到invoke中执行下一个拦截器
        if(MyApplication.isLoaded()){//执行自己的操作判断,我这里是判断伪代码是否登录
            inv.invoke();
        }else{//如果没有登录就跳转到登录页面,finish当前Activity
            Intent intent = new Intent(viewActivity, LoginActivity.class);
            viewActivity.startActivity(intent);
            viewActivity.finish();
        }
    }
}

四.拦截器的使用

一.自定义注释,来布局一个拦截器,当类实行的时候,会进行到BaseActivity的onResume方法中还记得上边包车型客车onResume吗

 //禁止子类的onResume方法
    @Override
    protected final void onResume() {
        super.onResume();
        //先定义一个长度为0的数组,避免全局数组为null
        Interceptor[] globalInters = InterceptorBuilder.NULL_INTERS;
        //获取全局的拦截器集合
        Interceptors interceptors = application.getInterceptors();
        if (interceptors != null) {
            globalInters = interceptors.getInterceptorArray();
        }
        //构造所有的拦截器(包括全局的当前Activity中的注释拦截器)
        Interceptor[] finalInters = InterceptorBuilder.build(globalInters, getClass());

        new Invocation(this, finalInters).invoke();//执行全局和当前类的拦截器
    }

2.拦截器的结构(通过类注释的点子来布局,当然也得以透过获得类的主意,那样比较直观,直接在类地点来定义)

public class InterceptorBuilder {
  public static final Interceptor[] NULL_INTERS = new Interceptor[0];

  private static Map<Class<? extends Interceptor>, Interceptor> intersMap = new HashMap<>();

  /**
   * 构建 Interceptors.
   * finalInters = globalInters + classInters
   */
  public static Interceptor[] build(Interceptor[] globalInters, Class<?> targetClass) {
      //1.存入全局的拦截器,添加到Map集合中
      for (Interceptor inter : globalInters)
          intersMap.put(inter.getClass(), inter);

      //2.获取Before注释的拦截器,如果有添加到Map集合中
      Interceptor[] classInters = createInterceptors(targetClass.getAnnotation(Before.class));

      // 3.判断是否有Clear注释
      Clear clear = targetClass.getAnnotation(Clear.class);

          //① 如果为null,就说明没有Clear ,直接将全局和Before构造成一个新的拦截器数组
      if (clear == null) {
          Interceptor[] result = new Interceptor[globalInters.length + classInters.length];
          int index = 0;
          for (Interceptor inter : globalInters)
              result[index++] = inter;
          for (Interceptor inter : classInters)
              result[index++] = inter;
          return result;
      }


      Class<? extends Interceptor>[] clearInters = clear.value();

           // ② 有Clear拦截器的标志,但是后面没有拦截器参数,意味着清楚所有其他的全局拦截器
             // (全局拦截器有很多,当不需要时,clear标志清除),只保留当前类Before拦截器
      if (clearInters.length == 0)
          return classInters;

          // ③ 有Clear拦截器的标志,后面也有Clear拦截器 则删除Map中Clear指定的拦截器,返回
      Interceptor[] temp = new Interceptor[globalInters.length + classInters.length];
      int index = 0;
      for (Interceptor inter : globalInters)
          temp[index++] = inter;
      for (Interceptor inter : classInters)
          temp[index++] = inter;

      int removeCount = 0;
      for (int i=0; i<temp.length; i++) {
          for (Class<? extends Interceptor> ci : clearInters) {
              if (temp[i].getClass() == ci) {//如果全局和当前类中有Clear标志的拦截器,置为null
                  temp[i] = null;
                  removeCount++;
                  break;
              }
          }
      }

      Interceptor[] result = new Interceptor[temp.length  - removeCount];//创建一个新的所有的拦截器数组,进行返回
      index = 0;
      for (Interceptor inter : temp)
          if (inter != null)
              result[index++] = inter;
      return result;
  }

  private static Interceptor[] createInterceptors(Before beforeAnnotation) {
      //为before为null,返回长度为0的数组
      if (beforeAnnotation == null)
          return NULL_INTERS;

      Class<? extends Interceptor>[] interceptorClasses = beforeAnnotation.value();
      //before注释后面没有拦截器的时候,返回长度为0的数组
      if (interceptorClasses.length == 0)
          return NULL_INTERS;


      //如果Map集合,全局拦截器没有该类上面的拦截器,就加入Map集合
      Interceptor[] result = new Interceptor[interceptorClasses.length];
      try {
          for (int i=0; i<result.length; i++) {
              result[i] = intersMap.get(interceptorClasses[i]);
              if (result[i] == null) {
                  result[i] = (Interceptor)interceptorClasses[i].newInstance();
                  intersMap.put(interceptorClasses[i], result[i]);
              }
          }
      } catch (Exception e) {
          throw new RuntimeException(e);
      }
      return result;
  }
}

3.自定义注释(Before和Clear接口,写在一道了)

@Inherited //可继承
@Retention(RetentionPolicy.RUNTIME)//保留的时间
@Target({ElementType.TYPE, ElementType.METHOD})//作用范围,类,接口方法等
public @interface Before {
    Class<? extends Interceptor>[] value();
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Clear {
    Class<? extends Interceptor>[] value() default {};
}

5.轻巧例子来反映拦截器的便宜

假若我们要去大保养肉体(也就是大家项目中的操作,须要查阅自个儿卡里还有多少钱,不过你无法不登陆才足以查阅),大养身须要杜蕾斯,倘若不采用拦截器,你每一遍去3回大养身,都要去买三次赤尾,很麻烦,而你选取了拦截器的话,就一定于您在衣袋之中已经装好了杜蕾斯,只供给大保养的时候拿出去就ok,那样就有利于了不少。接下来就是大保养身体的实战。。。

一.MainActivity,点击按键,去大保护健康,首先必须运用Clear,清除掉,(因为在大局默许配置了拦截器),否则也会拦截掉,就能够直接卡着,因为本身都还没图谋去啊,你就给自家拦截

@Clear(LoginInterceptor.class)
public class MainActivity extends BaseActivity implements View.OnClickListener {

    @Override
    public void onInitView(Bundle savedInstanceState) {
        super.onInitView(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt_has_login = (Button) findViewById(R.id.bt_has_login);
        Button bt_no_login = (Button) findViewById(R.id.bt_no_login);
        bt_has_login.setOnClickListener(this);
        bt_no_login.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
          //设置一个变量来处理事件,例如你的登录Token,用于判断Token有没有失效,失效则去登录
        if (view.getId() == R.id.bt_has_login) {
            MyApplication.setLoaded(true);//我有杜蕾斯
        } else if (view.getId() == R.id.bt_no_login) {
            MyApplication.setLoaded(false);//我没有杜蕾斯
        }
        go_yaozi();
    }

    //大保健
    private void go_yaozi() {
        Intent intent = new Intent(MainActivity.this, BeautifulGirlActivity.class);
        startActivity(intent);
    }
}

二.窑子来了

//在进窑子之前,判断是否有杜蕾斯,这里就会走入LoginInterceptor中
@Before(LoginInterceptor.class)
public class BeautifulGirlActivity extends BaseActivity {
    @Override
    public void onInitView(Bundle savedInstanceState) {
        super.onInitView(savedInstanceState);
        setContentView(R.layout.activity_girl);
    }
}

咱俩再来看看LoginInterceptor中的管理

public class LoginInterceptor implements Interceptor {

    @Override
    public void intercept(Invocation inv) {
        Activity viewActivity = inv.getView().getViewActivity();
        if(MyApplication.isLoaded()){//如果已经有杜蕾斯了,就去继续执行下一步
            inv.invoke();
        }else{//否则,回去拿杜蕾斯
            Intent intent = new Intent(viewActivity, LoginActivity.class);
            viewActivity.startActivity(intent);
            viewActivity.finish();
        }
    }
}

逛窑子逛到这里就逛完了,使用起来特别有利于,当3个项目有许多地点都急需使用的时候,就能够采用那种逛窑子的秘籍来管理,想再逛一回窑子的可以上去重新看下逛窑子的gif图。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 澳门新葡亰官网app 版权所有