1. Abstract classes
// Implement the view. OnClickListener interface
public abstract class OnThrottleClickListener implements View.OnClickListener {
private static final String TAG = "OnThrottleClickListener";
private static final int SKIP_DURATION = 300;//milliseconds
private long mLastClickTime;
@Override
public void onClick(View v) {
if (System.currentTimeMillis() - mLastClickTime > SKIP_DURATION) {
onThrottleClick(v);
mLastClickTime = System.currentTimeMillis();
} else {
Log.e(TAG, "OnThrottleClickListener: Repeat click"); }}protected abstract void onThrottleClick(View v);
}
Copy the code
// Instead of new view.onClickListener ()
id_tv_1.setOnClickListener(new OnThrottleClickListener() {
@Override
protected void onThrottleClick(View v) {
Log.e(TAG, "onClick: OnThrottleClickListener "); }});Copy the code
2. Proxy mode
// The proxy class implements the view. OnClickListener interface
public class ThrottleClickProxy implements View.OnClickListener {
private static final String TAG = "ThrottleClickProxy";
private static final int SKIP_DURATION = 300;//milliseconds
private long mLastClickTime;
/ / the source object
private View.OnClickListener mOriginListener;
/ / structure
public ThrottleClickProxy(View.OnClickListener mOriginListener) {
this.mOriginListener = mOriginListener;
}
@Override
public void onClick(View v) {
if (System.currentTimeMillis() - mLastClickTime >= SKIP_DURATION) {
mOriginListener.onClick(v);
mLastClickTime = System.currentTimeMillis();
} else {
Log.e(TAG, "ThrottleClickProxy: Repeat click"); }}}Copy the code
/ / use
id_tv_2.setOnClickListener(new ThrottleClickProxy(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: ThrottleClickProxy "); }}));Copy the code
3, RxBinding for RxAndroid
implementation 'com. Jakewharton. Rxbinding3: rxbinding: 3.0.0-1'
Copy the code
RxView.clicks(id_tv_3)
.throttleFirst(300, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
Log.e(TAG, "onClick: throttleFirst "); }});Copy the code
Eclipse AspectJ for AOP
// Use AspectJX to quickly configure Eclipse AspectJ
//project
dependencies {
classpath "Com. Android. Tools. Build: gradle: 4.1.2." "
//add
classpath 'com. Hujiang. Aspectjx: gradle - android plugin - aspectjx: 2.0.10'
}
Copy the code
plugins {
id 'com.android.application'
//add
id 'android-aspectjx'
}
//application module
dependencies {
//add
implementation 'org. Aspectj: aspectjrt: 1.9.5'
}
Copy the code
@Aspect
public class ThrottleClickAspect {
private static final String TAG = "ThrottleClickAspect";
private static final int SKIP_DURATION = 3000;
private long mLastClickTime;
. / / all android view. The view. An OnClickListener. OnClick method will be woven into, as the third party components RxView. On () will be, too
@Around("execution(* android.view.View.OnClickListener.onClick(..) )"
public void aroundViewOnClick(ProceedingJoinPoint joinPoint) throws Throwable {
if (System.currentTimeMillis() - mLastClickTime >= SKIP_DURATION) {
joinPoint.proceed();
mLastClickTime = System.currentTimeMillis();
} else {
Log.e(TAG, "ThrottleClickAspect: Repeat click"); }}}Copy the code
- Code is non-invasive. It’s working
Explicitly specified by annotation
- Add @throttleclick annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ThrottleClick {
int skipDuration(a) default 1000;
}
Copy the code
- Modify ThrottleClickAspect class
@Aspect
public class ThrottleClickAspect {
private static final String TAG = "ThrottleClickAspect";
private static final int SKIP_DURATION = 300;
// private int mLastClickViewId;
private long mLastClickTime;
// The declaration is the annotation mark pointcut
/ / package path
@Pointcut("execution(@com.louisgeek.aop.ThrottleClick * *(..) )"
public void pointcutThrottleClick(a) {
Log.e(TAG, "pointcutThrottleClick: ");
}
//
@Around("pointcutThrottleClick()")
public void aroundThrottleClick(ProceedingJoinPoint joinPoint) throws Throwable {
//
View view = null;
for (Object arg : joinPoint.getArgs()) {
if (arg instanceof View) {
view = (View) arg;
break; }}if (view == null) {
return;
}
// Retrieve the annotation of the method
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
if(! method.isAnnotationPresent(ThrottleClick.class)) {return;
}
ThrottleClick throttleClick = method.getAnnotation(ThrottleClick.class);
//
if (throttleClick == null) {
return;
}
int skipDuration = throttleClick.skipDuration();
if (skipDuration < 0) {
skipDuration = SKIP_DURATION;
}
if (System.currentTimeMillis() - mLastClickTime >= skipDuration) {
// Continue execution
joinPoint.proceed();
mLastClickTime = System.currentTimeMillis();
} else {
Log.e(TAG, AroundThrottleClick: Click again); }}}Copy the code
/ / use
id_tv_4.setOnClickListener(new View.OnClickListener() {
// Annotate the markup
@ThrottleClick
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: @ThrottleClick "); }});Copy the code