前言
在日常开发工作中,会碰到Button按钮点击处理用户的需求,比如提交一个订单到服务器或跳转进行支付按钮操作,如果出现延迟情况造成界面短时间没响应,用户接下来就很有可能再去点击一次按钮去提交,这样就的话会造成上一个事件还未处理完又多了一个新的事件需要处理,就会出现提交两次订单到后台服务器或支付两次。为了防止用户抖动多次点击造成的问题,就要从点击事件本身去寻找解决办法。
案件分析
一个普通的按钮点击后跳转到另一个页面的代码片段,如下:
-
//按钮点击事件:
-
Button.setOnClickListener(new OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
//比如 跳转到另一个Activity
-
}
-
});
分析:
正常情况下会跳转到另一页面,如果碰到手机比较卡的情况,或者用户手抖瞬间点击两次,就会造成点击事件被调用两次,页面跳转了2次。作为程序员首先会想到的就是在点击之后把Button设置为不可点击或不可用 :“clickable=false | | Enable=false”;但是,类似这样的button一个项目不知道有多少个,每个都要进行判断是否是Button是否可用,就会比较麻烦、代码也显得冗余。有么有更好滴解决办法呢?
解决方案一
利用规定响应时间,限制连续点击事件重复。
-
private long lastClickTime = 0;//1、上次点击的时间
-
@Override
-
public void onClick(View v) {
-
//2、判断距离上次点击小于2秒
-
if (System.currentTimeMillis() - lastClickTime <= 2000) {
-
//3、记录这次点击时间
-
lastClickTime = System.currentTimeMillis();
-
}
-
}
-
}
其实这个解决方案就是判断了一下时间差,容易理解。但问题是,每次都要写(复制)一堆代码,显得代码冗余,重用性不高,如果能够封装成工具类的方法,在每次点击事件发生之前调用一下就可以自行内部判断,这样就更好了嘛!
解决方案二
随着Rxjava事件流处理、响应式开发的观察者模式兴起,那么对于Android控件事件监听也有了变化,通过 RxBinding 把点击的事件监听转换成 Observable 之后,就有了对它进行扩展的可能。
这样可以使用RxBinding实现Button防抖问题处理。代码如下:(前后表示1.0\2.0版本用法有别)
-
button = (Button) findViewById( R.id.bt ) ;
-
RxView.clicks( button )
-
.throttleFirst( 2 , TimeUnit.SECONDS ) //两秒钟之内只取一个点击事件,防抖操作
-
.subscribe(new Action1<Void>() {
-
@Override
-
public void call(Void aVoid) {
-
Toast.makeText(MainActivity.this, "点击了", Toast.LENGTH_SHORT).show();
-
}
-
}) ;
-
RxView.clicks(button)
-
.throttleFirst( 2 , TimeUnit.SECONDS ) //两秒钟之内只取一个点击事件,防抖操作
-
.subscribe(new Consumer<Object>() {
-
@Override
-
public void accept(Object o) throws Exception {
-
Toast.makeText(MainActivity.this, "点击了", Toast.LENGTH_SHORT).show();
-
}
-
});