【Android AOP--02】防止按鈕連續點選
如果連續多次點選按鈕會造成開啟多個重複頁面,或者多次請求,造成資料混亂。所以很多時候,我們需要避免這種情況發生。下面就通過AOP來實現這個功能。
1、定義一個防止多次點選的工具類
/** * 防止按鈕2連續多次點選 * Created by zhouxu on 2018/9/17. */ public class NoDoubleClickUtils { private final static int SPACE_TIME = 500;//2次點選的間隔時間,單位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建立切面類,處理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
:表示這是一個切面類
@Around
:環繞通知,會攔截原方法內容的執行,也就是說會攔截Activity中的onclick(),只執行AspectTest的 onClickLitener()
proceedingJoinPoint.proceed();
:表示這個方法執行完畢了,可以放開攔截了,接下來就會執行Activity中的 onclick()
。
"execution(* android.view.View.OnClickListener.onClick(..))"
:表示切點,也就是說所有的點選事件,都會執行這個方法。
3、Activity中無需新增任何程式碼
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: "); } }); }
連續點選的執行結果

可以看出在Activity的onclick處只執行了一次,也就是說通過AOP這種方式,在不侵入原有程式碼的情況下,就實現了防止連續點選的功能。
如果說要求部分按鈕是可以連續點選的
這種情況,就需要自定義Pointcuts了。
1、自定義註解介面
/** * 自定義Pointcuts * Created by zhouxu on 2018/9/17. */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.CONSTRUCTOR, ElementType.METHOD}) public @interface DoubleClick { }
2、處理切面的類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中允許點選的onclick前加一個 @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) { //允許連續點選 Log.e(TAG, "button2 onClick: "); } }); } }
連續點選button2的執行結果

可以發現button1是不能連續點選的,而加了 @DoubleClick
註解的button2是可以連續點選的