如果連續(xù)多次點(diǎn)擊按鈕會(huì)造成打開(kāi)多個(gè)重復(fù)頁(yè)面,或者多次請(qǐng)求,造成數(shù)據(jù)混亂。所以很多時(shí)候,我們需要避免這種情況發(fā)生。下面就通過(guò)AOP來(lái)實(shí)現(xiàn)這個(gè)功能。
1、定義一個(gè)防止多次點(diǎn)擊的工具類(lèi)
/**
* 防止按鈕2連續(xù)多次點(diǎn)擊
* Created by zhouxu on 2018/9/17.
*/
public class NoDoubleClickUtils {
private final static int SPACE_TIME = 500;//2次點(diǎn)擊的間隔時(shí)間,單位ms
private static long lastClickTime;
public synchronized static boolean isDoubleClick() {
long currentTime = System.currentTimeMillis();
boolean isClick;
if (currentTime - lastClickTime > SPACE_TIME) {
isClick = false;
} else {
isClick = true;
}
lastClickTime = currentTime;
return isClick;
}
}
2、使用AspectJ創(chuàng)建切面類(lèi),處理Poincuts等
@Aspect
public class AspectTest {
final String TAG = AspectTest.class.getSimpleName();
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void onClickLitener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Log.e(TAG, "OnClick");
if (!NoDoubleClickUtils.isDoubleClick()) {
proceedingJoinPoint.proceed();
}
}
}
@Aspect:表示這是一個(gè)切面類(lèi)
@Around:環(huán)繞通知,會(huì)攔截原方法內(nèi)容的執(zhí)行,也就是說(shuō)會(huì)攔截Activity中的onclick(),只執(zhí)行AspectTest的onClickLitener()
proceedingJoinPoint.proceed();:表示這個(gè)方法執(zhí)行完畢了,可以放開(kāi)攔截了,接下來(lái)就會(huì)執(zhí)行Activity中的onclick()。
"execution(* android.view.View.OnClickListener.onClick(..))":表示切點(diǎn),也就是說(shuō)所有的點(diǎn)擊事件,都會(huì)執(zhí)行這個(gè)方法。
3、Activity中無(wú)需添加任何代碼
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "button1 onClick: ");
}
});
}
連續(xù)點(diǎn)擊的運(yùn)行結(jié)果

可以看出在Activity的onclick處只執(zhí)行了一次,也就是說(shuō)通過(guò)AOP這種方式,在不侵入原有代碼的情況下,就實(shí)現(xiàn)了防止連續(xù)點(diǎn)擊的功能。
如果說(shuō)要求部分按鈕是可以連續(xù)點(diǎn)擊的
這種情況,就需要自定義Pointcuts了。
1、自定義注解接口
/**
* 自定義Pointcuts
* Created by zhouxu on 2018/9/17.
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DoubleClick {
}
2、處理切面的類(lèi)AspectTest
@Aspect
public class AspectTest {
final String TAG = AspectTest.class.getSimpleName();
private boolean isDoubleClick = false;
@Before("execution(@com.zx.aopdemo.DoubleClick * *(..))")
public void beforeEnableDoubleClcik(JoinPoint joinPoint) throws Throwable {
Log.e(TAG, "beforeEnableDoubleClcik: ");
isDoubleClick = true;
}
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void onClickLitener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Log.e(TAG, "OnClick");
// if (!NoDoubleClickUtils.isDoubleClick()) {
// proceedingJoinPoint.proceed();
// }
if (isDoubleClick || !NoDoubleClickUtils.isDoubleClick()) {
proceedingJoinPoint.proceed();
isDoubleClick = false;
}
}
}
3、在Activity中允許點(diǎn)擊的onclick前加一個(gè)@DoubleClick的注解就好
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testAOP();
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "button1 onClick: ");
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@DoubleClick
@Override
public void onClick(View v) {
//允許連續(xù)點(diǎn)擊
Log.e(TAG, "button2 onClick: ");
}
});
}
}
連續(xù)點(diǎn)擊button2的運(yùn)行結(jié)果

可以發(fā)現(xiàn)button1是不能連續(xù)點(diǎn)擊的,而加了@DoubleClick注解的button2是可以連續(xù)點(diǎn)擊的