AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程仔涩,通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)忍坷。AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn)熔脂,也是Spring框架中的一個(gè)重要內(nèi)容佩研,是函數(shù)式編程的一種衍生范型。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離霞揉,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低旬薯,提高程序的可重用性,同時(shí)提高了開發(fā)的效率适秩。
Aop思想可以說成插樁绊序,在類的編譯期間中干一些東西硕舆,下圖看一個(gè)圖就明白了,主要關(guān)注一下AspectJ插入時(shí)機(jī)
接下來開始在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.配置排除第三方包名沖突,這一步不配置抚官,編譯的時(shí)候會(huì)報(bào)錯(cuò):java.util.zip.ZipException: zip file is empty
aspectjx{
exclude 'androidx','com.google','com.squareup','com.alipay','org.apache'
}
4.開始編寫一個(gè)防止雙擊的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)擊的時(shí)間
*/
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é)果