Android kotlin uses annotations to realize the anti button connection function

Time:2021-7-29

SingleClick:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class SingleClick(
    //Click interval, MS
    val value: Long = 500
)

SingleClickAspect:

import android.os.SystemClock
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut
import org.aspectj.lang.reflect.MethodSignature

@Aspect
class SingleClickAspect {

    /**
     *Define the tangent point and mark the tangent point as all the methods annotated by @ singleclick
     *Note: here, me.baron.test.annotation.singleclick needs to be replaced with
     *The full path of the singleclick class in your own project
     */
    @Pointcut ("execution (@ your package name. Singleclick * * (..)")
    fun methodAnnotated() { }

    /**
     *Define a tangent method, wrap tangent method
     */
    @Around("methodAnnotated()")
    @Throws(Throwable::class)
    fun aroundJoinPoint(joinPoint: ProceedingJoinPoint) {
        try {
            //Take out the annotation of the method
            val signature = joinPoint.signature as MethodSignature
            val method = signature.method
            //Check whether the method is annotated
            val hasAnnotation = method != null && method.isAnnotationPresent(SingleClick::class.java)
            if (hasAnnotation) {
                //Calculate the click interval. If there is no annotation, it is 500 by default. If there is annotation, it is calculated according to the annotation parameter. If the annotation parameter is empty, it is 500 by default;
                val singleClick = method.getAnnotation(SingleClick::class.java)
                val interval = singleClick.value
                //Detect whether the interval reaches the preset time and the thread is idle
                if (canClick(interval)) {
                    joinPoint.proceed()
                }
            } else {
                joinPoint.proceed()
            }
        } catch (e: Exception) {
            //Click events are not intercepted when exceptions occur
            joinPoint.proceed()
        }
    }

    //Determine whether to respond to click
    private fun canClick(interval: Long): Boolean {
        val time = SystemClock.elapsedRealtime()
        val timeInterval  = Math.abs(time - mLastClickTime)
        if (timeInterval > interval) {
            mLastClickTime = time
            return true
        }
        return false
    }

    companion object {
        //Time of last click
        private var mLastClickTime: Long = 0
    }

}

Build.gradle (project):

buildscript {
    dependencies {
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
    }
}

build.gradle(APP):

plugins {
    id 'android-aspectjx'
}

use:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:onClick="onTextClick"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    @SingleClick(800)
    fun onTextClick(view: View) {

    }
}