Android開發(fā)中很多場景都需要在短時(shí)間內(nèi)避免重復(fù)點(diǎn)擊一個(gè)按鈕造成不必要的麻煩,就可以使用AOP的方式來實(shí)現(xiàn)這個(gè)功能。
一咆贬、使用AOP(面向切面編程,Android中是OOP面向?qū)ο缶幊蹋┦紫纫赟tudio中集成AOP帚呼。
????集成AOP步驟:
????????1,在project的build文件中添加依賴: 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'皱蹦。(gradle版 本大于4需要aspectjx2.0以上)
? ? ? ? ?2煤杀,在app項(xiàng)目中(有‘com.android.application’的文件中)添加插 件
????????????apply plugin: 'com.hujiang.android-aspectjx';
????????????添加aspectjx {//排除所有package路徑中包含`android.support`的class文件及庫(jar 文件)? ? ? ????????????exclude {'android.support','com.google'}
? ? ? ? ?3沪哺,在需要使用的項(xiàng)目或庫中添加 'org.aspectj:aspectjrt:1.8.+'沈自。
驗(yàn)證是否集成成功:隨便找一個(gè)類,在類名的上方使用注解@Aspect有效辜妓,就代表集成成功了枯途。
二忌怎、新建一個(gè)類,類名隨便
??
這個(gè)類文件保存在依賴module(沒有就在主app module中)中任意package下就行了酪夷。不用任何配置或其他代碼處理榴啸,代碼中所有OnClickListener的地方就都會先判斷是否是快速點(diǎn)擊,然后再執(zhí)行晚岭,達(dá)到防止重復(fù)點(diǎn)擊的目標(biāo)鸥印。
注意:上面有個(gè)?@RepeatClick注解的使用,如果有的場景不需要避免重復(fù)點(diǎn)擊坦报,就在onClick方法上加上這個(gè)注解库说。? ?
``javascript
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD})
public @interface RepeatClick {
}
``
使用方法:這個(gè)onclik中的點(diǎn)擊事件就不會有點(diǎn)擊事件攔截了
終極優(yōu)化方案:不是同一個(gè)View的點(diǎn)擊,不進(jìn)行點(diǎn)擊過濾
```
//上次點(diǎn)擊的時(shí)間
private static Long sLastclick =0L;
//攔截所有兩次點(diǎn)擊時(shí)間間隔小于一秒的點(diǎn)擊事件
private static final Long FILTER_TIMEM =1000L;
//上次點(diǎn)擊事件View
private View lastView;
//---- add content -----
//是否過濾點(diǎn)擊 默認(rèn)是
private boolean checkClick =true;
//---- add content -----
@Around("execution(* android.view.View.OnClickListener.onClick(..))")
public void onClickLitener(ProceedingJoinPoint proceedingJoinPoint)throws Throwable {
//大于指定時(shí)間
? ? if (System.currentTimeMillis() -sLastclick >=FILTER_TIMEM) {
????????doClick(proceedingJoinPoint);
????}else {
????//---- update content -----? 判斷是否需要過濾點(diǎn)擊
? ? ? ? //小于指定秒數(shù) 但是不是同一個(gè)view 可以點(diǎn)擊? 或者不過濾點(diǎn)擊
? ? ? ? if (!checkClick ||lastView ==null ||lastView != (proceedingJoinPoint).getArgs()[0]) {
//---- update content -----? 判斷是否需要過濾點(diǎn)擊
? ? ? ? ? ? doClick(proceedingJoinPoint);
????????}else {
//大于指定秒數(shù) 且是同一個(gè)view
? ? ? ? ? ? LogUtils.e(TAG,"重復(fù)點(diǎn)擊,已過濾");
????????}
????}
}
//執(zhí)行原有的 onClick 方法
private void doClick(ProceedingJoinPoint joinPoint)throws Throwable {
//判斷 view 是否存在
? ? if (joinPoint.getArgs().length ==0) {
????????joinPoint.proceed();
????????return;
}
//記錄點(diǎn)擊的view
? ? lastView = (View) (joinPoint).getArgs()[0];
//---- add content -----
? ? //修改默認(rèn)過濾點(diǎn)擊
? ? checkClick =true;
//---- add content -----
? ? //記錄點(diǎn)擊事件
? ? sLastclick =System.currentTimeMillis();
//執(zhí)行點(diǎn)擊事件
? ? try {
????????joinPoint.proceed();
????}catch (Throwable throwable) {
????????throwable.printStackTrace();
????}
}
@Before("execution(@包名.RepeatClick? * *(..))")
public void beforeEnableDoubleClcik(JoinPoint joinPoint)throws Throwable {
????checkClick =false;
}
```