kotlin 使用aop插件aspectjx踩坑之路(防止按钮重复点击)

前言

在我的上一篇博文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切面控制按钮重复点击已经完成了。

猜你喜欢

转载自blog.csdn.net/freak_csh/article/details/89705422