一、前言
通常android系统需要做一些统一的处理,最简单的选择是在BaseActivity中,但是由于BaseActivity的
1,强侵入性(改变原有代码结构)
2,java的硬编码特性(在预编译阶段需要存在才能处理,但大部分源码sdk已经写死了不可能单独生成自己的一个sdk)
这样就使得AOP特别的火爆,这里以入门基础hook为知识点,以最简单的防抖处理为例实战一下。
java常用编程思想面向过程(POP)、面向对象(OOP)、面向接口(IOP)、面向切面(AOP)区别:
- 面向过程:典型的是C/C++的结构体,结构体里只有变量,没有处理变量的方法,需要专门编写处理变量的方法。
- 面向对象:ArrayList list=new ArrayList();坏处是如果改为LinkedList,所有代码可能需要重写,同时扩展一个新的List的话,需要重新调用。
- 面向接口:List=new Arraylist();是面向对象的一种形式,广义上讲,抽象类也是接口的一种形式,使用该类的某种属性(接口)来表示,降低耦合性,增加代码复用性。
- 面向切面:这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
二、环境配置
首先我们需要配置SpringAOP的插件依赖,在项目根目录下配置插件版本,并且在需要依赖的module中依赖该插件,同时也要引入该jar包。
三、AOP代码实现
这里我们新建一个带插件注解的类作为aop的入口,然后在该类中声明具体的拦截器。从拦截器返回的连接点中取出我们的实例对象view,从而实现务无侵入式点击事件的拦截。
@Aspect
public class AspectDoubleClick {
private long delayTime = 2000;
private long lastTime; //上次间隔时间
private View lastView; //点击的view
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void onClickListener(ProceedingJoinPoint joinPoint) throws Throwable {
//获取连接点方法运行时的入参列表(这里拦截的是触发增强动作的控件)
Object[] args = joinPoint.getArgs();
View view = (View) args[0];//这里取第一个即可
if (view != lastView) { //不是同一个View直接过
joinPoint.proceed();
lastView = view;
lastTime = System.currentTimeMillis();
return;
}
if (System.currentTimeMillis() - lastTime >= delayTime) {
joinPoint.proceed();
lastTime = System.currentTimeMillis();
lastView = view;
}
}
}
到此一个简单的防重复点击已经实现,可以算结束了,我们运行项目效果图如下
三、完美实现
但是这里统一拦截仍存在以下弊端 1,部分点击事件不需要拦截如何处理 2,部分点击事件需要延迟的与全局的2000ms不一样如何简单处理
3,部分activity中的页面都不需要拦截如何统一处理 4,绝大部分事件是带有状态的如何简单处理(比如登录了才能点击)
5,在统一拦截下,只有极少个点击事件需要特殊自定义的如何处理 那么后面可以参看这个详细版的,源代码注释明确