AspectJX基于AspectJ并在此基础上扩展出来可应用于Android开发平台的AOP框架,可作用于java源码,class文件及jar包,同时支持kotlin的应用。
AOP思想
AOP是面向切面编程,它在我们日志系统,权限管理,事件统一回调拦截,有着较好的应用。
在项目中,我们的很多的功能都分散到各个模块中,AOP的目的就是把他们集中起来放在一个统一的地方做管理。
AspectJ
AspectJ是AOP思想的一个具体实现方案,就是这样的一个工具。使用AspectJ一般用两种方式,一种是完全用AspectJ的语言开发,另一种是使用Java中的@Aspect注解
具体使用
@Aspect
public class SingleClickAOP {
//上次点击的时间
private static Long sLastClick = 0L;
//拦截所有两次点击时间间隔小于一秒的点击事件
private static final Long FILTER_TIME_UNIT = 1000L;
//上次点击事件View
private View lastView;
// 定义切入点:View.OnClickListener#onClick()方法
@Pointcut("execution(* android.view.View.OnClickListener.onClick(..))")
private void methodViewOnClick() {
}
//直接setOnClickListener 拦截点击事件
@Around("methodViewOnClick()")
public void clickFilterHook(ProceedingJoinPoint joinPoint) throws Throwable {
//大于指定时间
if (System.currentTimeMillis() - sLastClick >= FILTER_TIME_UNIT) {
Log.d(Constant.TAG, "AspectJX 单次点击");
doClick(joinPoint);
} else {
//小于指定秒数 但是不是同一个view 可以点击 或者不过滤点击
if (lastView == null || lastView != (joinPoint).getArgs()[0]) {
doClick(joinPoint);
} else {
//大于指定秒数 且是同一个view
Log.d(Constant.TAG, "AspectJX 重复点击,已过滤");
}
}
}
//执行原有的 onClick 方法
private void doClick(ProceedingJoinPoint joinPoint) throws Throwable {
//判断 view 是否存在
if (joinPoint.getArgs().length == 0) {
joinPoint.proceed();
return;
}
//记录点击的 view(最好加上捕获类型转换异常的try)
lastView = (View) (joinPoint).getArgs()[0];
//记录点击事件
sLastClick = System.currentTimeMillis();
//执行点击事件
try {
joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
采坑:
1:
Default interface methods are only supported starting with Android N (--min-api 24):
Lorg/aspectj/lang/ProceedingJoinPoint;stack$AroundClosure(Lorg/aspectj/runtime/inte
rnal/AroundClosure;)V
将Java Version升级为1.8
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
2:
Caused by: java.util.zip.ZipException: zip file is empty
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:225)
at java.util.zip.ZipFile.(ZipFile.java:279)
at com.android.tools.r8.ArchiveClassFileProvider.(:24)
at com.android.tools.r8.ArchiveClassFileProvider.(:1)
at com.android.builder.dexing.r8.CachingArchiveClassFileProvider.(CachingArchiveClassFileProvider.java:32)
at com.android.builder.dexing.r8.ClassFileProviderFactory.createProvider(ClassFileProviderFactory.java:123)
at com.android.builder.dexing.r8.ClassFileProviderFactory.(ClassFileProviderFactory.java:93)
at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.transform(DexArchiveBuilderTransform.java:369)
... 99 more
在project的build.gralde里面加入
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
在app的build.gradle里面加入
apply plugin: 'android-aspectjx'
api 'org.aspectj:aspectjrt:1.9.5'
aspectjx {
enabled true
exclude 'com.google'
}