在我的上一篇博文Android处理按钮重复点击事件中,介绍了AOP切面编程处理按钮的重复点击问题,最近在学习kotlin,基于kotlin也是使用java的,所以也想在kotlin写一个,也就有了以下的踩坑之路。
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
apply plugin: 'com.hujiang.android-aspectjx'
dependencies {
implementation 'org.aspectj:aspectjrt:1.8.13'
}
注意:如果aspectjx是在module或者library中引入依赖,则在app的build.gradle也需要添加依赖,要不就在使用module或者library中的aop注解就无法生效。(具体原因还未发现)
特别提醒:在根目录下导入的aspectjx版本一定要是2.0.4或者2.0.2版本,因为在之前的版本中无法识别kotlin写的Aspect文件,所以要特别注意。aspectjx的github地址如下:
https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
还有,建议使用最新版的kotlin插件,下面贴出当前我的版本依赖:
buildscript {
ext.kotlin_version = '1.3.31'
repositories {
google()
jcenter()
}
dependencies {
// classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
当前最新版本为1.3.31版本,如果不是最新可以到以下网址查看:
http://www.kotlincn.net/docs/reference/using-gradle.html 中文版
https://kotlinlang.org/docs/reference/using-gradle.html 英文版
如果在编译过程中出现Error:Failed to resolve: org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.31错误,则可点击查看我的博文,里面有解决方案。
如果错线Could not find matching constructor for: org.gradle.util.Clock()错误,在这个博文中有解决方案。
/**
* AnnotationRetention.SOURCE:不存储在编译后的 Class 文件。
* AnnotationRetention.BINARY:存储在编译后的 Class 文件,但是反射不可见。
* AnnotationRetention.RUNTIME:存储在编译后的 Class 文件,反射可见。
*/
@Retention(AnnotationRetention.RUNTIME)
/**
* AnnotationTarget.CLASS:类,接口或对象,注解类也包括在内。
* AnnotationTarget.ANNOTATION_CLASS:只有注解类。
* AnnotationTarget.TYPE_PARAMETER:Generic type parameter (unsupported yet)通用类型参数(还不支持)。
* AnnotationTarget.PROPERTY:属性。
* AnnotationTarget.FIELD:字段,包括属性的支持字段。
* AnnotationTarget.LOCAL_VARIABLE:局部变量。
* AnnotationTarget.VALUE_PARAMETER:函数或构造函数的值参数。
* AnnotationTarget.CONSTRUCTOR:仅构造函数(主函数或者第二函数)。
* AnnotationTarget.FUNCTION:方法(不包括构造函数)。
* AnnotationTarget.PROPERTY_GETTER:只有属性的 getter。
* AnnotationTarget.PROPERTY_SETTER:只有属性的 setter。
* AnnotationTarget.TYPE:类型使用。
* AnnotationTarget.EXPRESSION:任何表达式。
* AnnotationTarget.FILE:文件。
* AnnotationTarget.TYPEALIAS:@SinceKotlin("1.1") 类型别名,Kotlin1.1已可用。
*/
@Target(AnnotationTarget.FUNCTION)
annotation class AopOnclick(
/**
* 点击间隔时间
*/
val value: Long = 1000)
object AopClickUtil {
/**
* 最近一次点击的时间
*/
private var mLastClickTime: Long = 0
/**
* 是否是快速点击
*
* @param intervalMillis 时间间期(毫秒)
* @return true:是,false:不是
*/
fun isFastDoubleClick(intervalMillis: Long): Boolean {
// long time = System.currentTimeMillis();
val time = SystemClock.elapsedRealtime()
val timeInterval = Math.abs(time - mLastClickTime)
return if (timeInterval < intervalMillis) {
true
} else {
mLastClickTime = time
false
}
}
}
@Aspect
class AopClickAspect {
/**
* 定义切点,标记切点为所有被@AopOnclick注解的方法
* 注意:这里com.freak.kotlinhttpmanager.aop.AopOnclick需要替换成
* 你自己项目中AopOnclick这个类的全路径
*/
@Pointcut("execution(@com.freak.kotlinhttpmanager.aop.AopOnclick * *(..))")
fun methodAnnotated() {
}
/**
* 定义一个切面方法,包裹切点方法
*/
@Around("methodAnnotated()")
@Throws(Throwable::class)
fun aroundJoinPoint(joinPoint: ProceedingJoinPoint) {
// 取出方法的注解
val methodSignature = joinPoint.signature as MethodSignature
val method = methodSignature.method
if (!method.isAnnotationPresent(AopOnclick::class.java)) {
return
}
val aopOnclick = method.getAnnotation(AopOnclick::class.java)
// 判断是否快速点击
if (!AopClickUtil.isFastDoubleClick(aopOnclick.value)) {
// 不是快速点击,执行原方法
joinPoint.proceed()
}
}
}
方式一:实现View.OnClickListener接口,在实现方法上面加入注解@AopOnclick,示例如下:
@AopOnclick
override fun onClick(v: View?) {
when (v?.id) {
R.id.aop -> {
LogUtil.e("点击")
}
}
}
方式二:直接点击事件设置
aop.setOnClickListener {
aop()
}
@AopOnclick(2000)
fun aop() {
text2.text = "aop自定义时间点击次数:${saopSum++}次"
}
因为kotlin没有跟java一样有实现方法,所以可以自定义一个方法,在方法上面加入注解即可。
@AopOnclick(2000):2000是自定义的时间,也就是说,设置2秒之内不能重复点击
也可以使用@AopOnclick,默认时间是1000,也就是1秒
到此,aop切面控制按钮重复点击已经完成了。