AOP在Android開發(fā)中的使用

AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運(yùn)行期動態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點(diǎn),也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
Aop思想可以說成插樁,在類的編譯期間中干一些東西,下圖看一個圖就明白了,主要關(guān)注一下AspectJ插入時機(jī)


image.png

接下來開始在Android開發(fā)中引入AOP

由于現(xiàn)在Kotlin已經(jīng)成Android開發(fā)的趨勢,AOP的適配也需要兼容Kotlin,所以這里引用github開源項(xiàng)目實(shí)現(xiàn)
github開源項(xiàng)目:https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx

1.引入插件
buildscript {
    ext.kotlin_version = '1.3.61'
    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" }
    }
    dependencies {
        //我這里使用的是3.6.2
        classpath 'com.android.tools.build:gradle:3.6.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        //最新版本為2.1.0
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
    }
}
2.應(yīng)用插件
apply plugin: 'android-aspectjx'
3.配置排除第三方包名沖突,這一步不配置,編譯的時候會報(bào)錯:java.util.zip.ZipException: zip file is empty
aspectjx{
    exclude 'androidx','com.google','com.squareup','com.alipay','org.apache'
}
4.開始編寫一個防止雙擊的AOP

定義注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SingleClick {

    /**
     * 快速點(diǎn)擊的間隔
     */
    long value() default 1000;
}

實(shí)現(xiàn)注解,在方法切入點(diǎn)修改成自己使用的切入規(guī)則

@Aspect
public class SingleClickAspect {

    /**
     * 最近一次點(diǎn)擊的時間
     */
    private long mLastTime;
    /**
     * 最近一次點(diǎn)擊的控件ID
     */
    private int mLastId;

    /**
     * 方法切入點(diǎn)
     */
    @Pointcut("execution(@com.sunnet.shipcargo.aop.SingleClick * *(..))")
    public void method() {}

    /**
     * 在連接點(diǎn)進(jìn)行方法替換
     */
    @Around("method() && @annotation(singleClick)")
    public void aroundJoinPoint(ProceedingJoinPoint joinPoint, SingleClick singleClick) throws Throwable {
        View view = null;
        for (Object arg : joinPoint.getArgs()) {
            if (arg instanceof View) {
                view = (View) arg;
            }
        }
        if (view != null) {
            long currentTime = Calendar.getInstance().getTimeInMillis();
            if (currentTime - mLastTime < singleClick.value() && view.getId()
                    == mLastId) {
                Log.i("SingleClick", "發(fā)生快速點(diǎn)擊");
                return;
            }
            mLastTime = currentTime;
            mLastId = view.getId();
            //執(zhí)行原方法
            joinPoint.proceed();
        }
    }
}
5.使用
/**
     * 發(fā)送驗(yàn)證碼
     */
    @SingleClick
    private fun sendCode(view: View){
        Log.d("驗(yàn)證碼", "驗(yàn)證碼")
    }

運(yùn)行結(jié)果


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容