在Android的代码实现中,我们不可避免的会经常跟点击事件setOnClickListener打交道。
而重复点击又是我们不得不面对的问题。市面上的大厂的app 都对快速点击进行了操作,下面就来说一说解决快速点击的几种方案。
1.java实现
public class FastClickUtil {private static final int MIN_CLICK_DELAY_TIME = 500;//两次点击间隔不少于0.5sprivate static long lastClickTime = 0;public static boolean isFastClick() {boolean flag;long curClickTime = System.currentTimeMillis();if (curClickTime - lastClickTime > MIN_CLICK_DELAY_TIME) {lastClickTime = curClickTime;flag = true;} else {flag = false;}return flag;}
}view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if(FastClickUtil.isFastClick()) {//todo something}}});
但是上面这种方法会有一种问题,如果你点击了一个按钮之后触发了点击时间lastClickTime的时间记录了最后一次点击的时间,现在调整了系统的时间,向前调整XX时间,那curClickTime - lastClickTime 永远也不会大于0.5s 也就是点击时间永远都不会再触发了。调整系统的时间的操作不属于常规操作,但是我们的QA还是会测试用例,所以不得不改了。
2.RXjava实现,
rxjava已经出了很久了 ,现在已经很成熟了。线程的调度,链式编程,还有它本身自带的一些优秀API,都是我们要用它的理由。
public class RxViewUtils {private static final int DELAYED_TIME = 1000;//Anti-jitter duration in milliseconds/*** Prevent duplicate clicks** @param target Objective view* @param consumer Click on the callback*/public static void setOnClickListeners(@NonNull final View target, Consumer<View> consumer) {setOnClickListeners(target, consumer, DELAYED_TIME);}/*** Prevent duplicate clicks, support custom anti-jitter duration** @param target Objective view* @param consumer Click on the callback* @param delayedTime Delay time*/public static void setOnClickListeners(@NonNull final View target, Consumer<View> consumer, int delayedTime) {Observable.create(new ObservableOnSubscribe<View>() {@Overridepublic void subscribe(final ObservableEmitter<View> emitter) {View.OnClickListener listener = new View.OnClickListener() {@Overridepublic void onClick(View v) {if (!emitter.isDisposed()) {emitter.onNext(target);}}};target.setOnClickListener(listener);}}).throttleFirst(delayedTime, TimeUnit.MILLISECONDS).subscribe(consumer);}
使用:
RxViewUtils.setOnClickListeners(mRecyclerView, new Consumer<View>() {@Overridepublic void accept(View view) throws Exception {//todo something}});
//我们用了rxjava的throttleFirst操作符,在规定时间内 只会触发一次事件,这个会比第一种方法优雅一点。当然还可以用rxAndroid里面的
RxView.clicks(view).throttleFirst(1, TimeUnit.SECONDS).subscribe(new Consumer<Object>() {@Overridepublic void accept(Object o) throws Exception {// do something}});
3.通过注解来完成点击这里
这个缺点的话就是,在运行期间需要再去操作,所以在性能上面会又一点影响,但是影响不大