防止連續點擊的實現方式有很多種,比如,在所有的onclick裡面加上防多次點擊的代碼,或者定義一個新的OnClickListener,在裡面加上防多次點擊的代碼,然後項目中的所有OnClickListener都用這個listener,當然還有一些其他的方式,這裡將介紹一種新的方式來實現,那就是aop ...
防止連續點擊的實現方式有很多種,比如,在所有的onclick裡面加上防多次點擊的代碼,或者定義一個新的OnClickListener,在裡面加上防多次點擊的代碼,然後項目中的所有OnClickListener都用這個listener,當然還有一些其他的方式,這裡將介紹一種新的方式來實現,那就是aop。
不知道aop的可以看這篇文章深入理解Android之AOP
在android實現aop通常是用AspectJ來實現,AspectJ的用法可以看這篇文章AspectJ基本用法.
使用OnClickLitener的代碼
public class MainActivity extends AppCompatActivity {
final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "execute click");
}
});
}
}
首先定義一個防止多次點擊的工具類
public class NoDoubleClickUtils {
private static long lastClickTime = 0;
private final static int SPACE_TIME = 500;
public synchronized static boolean isDoubleClick() {
long currentTime = System.currentTimeMillis();
boolean isClick2;
if (currentTime - lastClickTime >
SPACE_TIME) {
isClick2 = false;
} else {
isClick2 = true;
}
lastClickTime = currentTime;
return isClick2;
}
}
然後使用AspectJ對OnclickLitener進行插樁,
@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();
}
}
}
運行程式,多次點擊按鈕後,log如下
04-03 19:41:20.043 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.043 5784-5784/ E/MainActivity: execute click
04-03 19:41:20.222 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.377 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.542 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.689 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.838 5784-5784/ E/AspectTest: OnClick
04-03 19:41:21.012 5784-5784/ E/AspectTest: OnClick
04-03 19:41:21.158 5784-5784/ E/AspectTest: OnClick
通過log可以看出onClickLitener執行了多次,但使用clcik的的地方只執行了一次。這樣,就可以在不改變原來代碼的情況下,實現防止連續點擊的功能。
但是當又有需求:要求部分按鈕是可以連續點擊的,該怎麼辦能?這個時候只要加個註解文件就好。
首先定義個註解
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DoubleClick {
}
並且修改之前的AspectTest文件
private boolean canDoubleClick = false;
@Before("@annotation(*..DoubleClick)")
public void beforeEnableDoubleClcik(JoinPoint joinPoint) throws Throwable {
canDoubleClick = true;
}
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void OnClickListener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Log.e(TAG, "OnClick:");
if (canDoubleClick || !NoDoubleClickUtils.isDoubleClick()) {
proceedingJoinPoint.proceed();
canDoubleClick = false;
}
}
現在只要在可以連續點擊的按鈕的onclick前加一個@DoubleClick的註解就好,將MainActivty修改如下
public class MainActivity extends AppCompatActivity {
final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "text execute click");
}
});
findViewById(R.id.text2).setOnClickListener(new View.OnClickListener() {
@DoubleClick
@Override
public void onClick(View v) {
Log.e(TAG, "text2 execute click");
}
});
}
}
運行程式,分別連續點擊第一個view和第二個view,log如下
04-03 21:35:27.304 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:27.304 21347-21347/ E/MainActivity: text execute click
04-03 21:35:27.464 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:27.645 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:27.776 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:27.948 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:28.104 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:28.277 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:28.441 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:28.605 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:28.770 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:35.533 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:35.533 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:35.715 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:35.715 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:35.862 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:35.862 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:36.026 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:36.026 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:36.199 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:36.199 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:36.355 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:36.355 21347-21347/ E/MainActivity: text2 execute click
04-03 21:35:36.520 21347-21347/ E/AspectTest: OnClick:
04-03 21:35:36.520 21347-21347/ E/MainActivity: text2 execute click
可以發現第一個view不能被連續點擊了,但第二個可以連續點擊。