前言
在我的上一篇博文Android处理按钮重复点击事件中,介绍了AOP切面编程处理按钮的重复点击问题,最近在学习kotlin,基于kotlin也是使用java的,所以也想在kotlin写一个,也就有了以下的踩坑之路。
使用方法:
1.引入Aspectj
- 在项目根目录下的build.gradle中,添加依赖
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
- 在app或其他module目录下的build.gradle中,添加以下代码:
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文件,所以要特别注意。
还有,建议使用最新版的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()错误,在这个博文中有解决方案。
2、添加一个自定义注解
/** * 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)
3、封装一个重复点击判断工具类
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 } } }
4、编写Aspect AOP处理类
@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切面控制按钮重复点击已经完成了。