美文网首页Android界面端
安卓按钮防抖动之终极解决方案

安卓按钮防抖动之终极解决方案

作者: tanbiheng | 来源:发表于2018-01-22 14:36 被阅读492次

    开发过程中,我们经常会用到OnClick点击事件,常用的写法可能是这样的:

    btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    //TODO
                }
            });
    

    或者是这样的:

    btn.setOnClickListener(this);
    
    @Override
    public void onClick(View v) {
       //TODO
    }
    

    正常情况下,这样的代码是没有什么问题的,但是大家都知道安卓碎片化严重,每个手机的性能也千差万别。想必大家都遇到过,在比较卡的手机上,快速点击按钮打开一个页面,结果发现这个页面被打开了两次...

    一般这种情况下,我们会打开百度,看看万能的网友都是怎么处理这种问题的(当时我就是这么做的😳),搜索到的处理方式可能是这样的:

    btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    //TODO
                    btn.setClickable(false);
                    btn.setEnabled(false);
                }
            });
    

    也可能是这样的:

    public abstract class NoDoubleClickListener implements OnClickListener {
    
        public static final int MIN_CLICK_DELAY_TIME = 1000;
        private long lastClickTime = 0;
    
        @Override
        public void onClick(View v) {
            long currentTime = Calendar.getInstance().getTimeInMillis();
            if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME{
                lastClickTime = currentTime;
                onNoDoubleClick(v);
            } 
         }  
     
        public abstract void onNoDoubleClick(View v);
    }
    
    btn.setOnClickListener(new NoDoubleClickListener() {
                @Override
                public void onNoDoubleClick(View v) {
                     //TODO
                }
            }); 
    

    还有的说用RxBinding,由于涉及到Rxjava相关的知识,篇幅原因,我这里就不过多描述,感兴趣的同学可以自行百度了解。

    当然,上述几种方式均能达到防止按钮快速点击,但是其弊端也比较明显。先说第一种方式,这种方法虽然可以防止快速点击,但是其给体验上的影响还是非常大的,想想如果你这个按钮点击后会有网络请求,如果网络请求执行过程比较长的话,按钮一直无法被点击,会让用户以为出现了bug;方式二相比第一种方法,体验上倒是没什么问题,但是其弊端在于只能通过匿名内部类的方式注册点击事件,当出现一个界面按钮比较多,写起来代码就显得比较臃肿了。

    说了这么多,是时候展示真正的技术了,不多BB,直接上代码。

    首先我们定义一个点击事件接口

    public interface OnLimitClickListener {
    
        /**
         * 按钮点击事件
         * @param view
         */
        void onClick(View view);
    
    }
    

    再定义一个抽象类对我们的点击事件做一层包装

    public class OnLimitClickHelper implements View.OnClickListener {
        public static final int LIMIT_TIME = 300;
        private long lastClickTime = 0;
        private OnLimitClickListener onLimitClickListener = null;
    
        public OnLimitClickHelper(OnLimitClickListener onLimitClickListener){
            this.onLimitClickListener = onLimitClickListener;
        }
    
        @Override
        public void onClick(View v) {
            long curTime = Calendar.getInstance().getTimeInMillis();
            if (curTime - lastClickTime > LIMIT_TIME) {
                lastClickTime = curTime;
                if(onLimitClickListener != null){
                    onLimitClickListener.onClick(v);
                }
            }
        }
    }
    

    ok,完工!😂😂😂

    最后我们看看Activity的使用:

    public abstract class MainActivity extends AppCompatActivity implements OnLimitClickListener {
        private Button btn = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn = findViewById(R.id.btn);
            btn.setOnClickListener(new OnLimitClickHelper(this));
        }
    
        @Override
        public void onClick(View v) {
            //TODO
        }
    }
    

    觉得写的不错的朋友,帮忙点下喜欢,你们的支持是我创作的动力!大家有什么问题也可以在下方评论,有时间我会一一解答,感谢!

    相关文章

      网友评论

      • AWeiLoveAndroid:你这个代码还是有问题的,我试着写了一下 btn.setOnClickListener(new OnLimitClickHelper(this));这个地方是报错的 因为setOnClickListener里面传入的是View.OnClickListener接口 不是你的那个类 建议按照我这样改进比较好
        public class MyClickListener implements View.OnClickListener{

        public static final int LIMIT_TIME = 300;
        private long lastClickTime = 0;
        private View.OnClickListener mClickListener = null;

        public MyClickListener(View.OnClickListener onClickListener){
        this.mClickListener = onClickListener;
        }

        @Override
        public void onClick(View v) {
        long curTime = Calendar.getInstance().getTimeInMillis();
        if (curTime - lastClickTime > LIMIT_TIME) {
        lastClickTime = curTime;
        if(mClickListener != null){
        mClickListener.onClick(v);
        }
        }
        }
        }
        tanbiheng:@AWeiLoveAndroid GitHub上有源码,但是示例代码还没来得及整理,不过你可以先去看看,以后博客更新的内容,代码都会同步上去
        AWeiLoveAndroid:@tanbiheng 可以把源码放github吗
        tanbiheng:我自己项目就在用这个,报错可能是你自己代码哪里写的不对

      本文标题:安卓按钮防抖动之终极解决方案

      本文链接:https://www.haomeiwen.com/subject/gjqlaxtx.html