美文网首页我爱编程Android 进阶技术篇专题安卓开发博客
Android 这才是实现防抖动(防快速点击)的最优雅写法

Android 这才是实现防抖动(防快速点击)的最优雅写法

作者: SwitchLife | 来源:发表于2018-07-01 23:52 被阅读41次

    开篇

    这篇我们要弄清楚以下两个问题:

    • 1、为什么要做防抖动点击?

      做防抖动点击的目的很简单:我们需要追求更高更优质的用户体验。当我们无意间快速多次点击某一个Button跳转界面时会弹出N个相同的界面,这就很影响用户体验性,为此我们不得不限制快速多次点击同一个Button。

    • 2、防抖动点击原理是什么?

      在快速多次点击中,我们只取其中一次点击事件,忽略其余的点击事件。我们通常的做法就是在一定的时间间隔内只取其中一次点击事件。

    弄清楚了上面两个问题,下面着手实现逻辑。
    这里链接几篇别人写的防抖动点击的相关博文:

    都写得非常不错,但是,要么就是复杂化,要么就是用起来不方便。为止我琢磨出来了一套自己写法,简单易懂,用起来灰常方便。

    立即体验

    扫描以下二维码下载体验App(从0.2.3版本开始,体验App内嵌版本更新检测功能):


    JSCKit库传送门:https://github.com/JustinRoom/JSCKit

    工具类源码

    AntiShakeUtils.java

    /**
     * 防抖动点击
     *
     * @author jiangshicheng
     */
    public class AntiShakeUtils {
    
        private final static long INTERNAL_TIME = 1000;
    
        /**
         * Whether this click event is invalid.
         *
         * @param target target view
         * @return true, invalid click event.
         * @see #isInvalidClick(View, long)
         */
        public static boolean isInvalidClick(@NonNull View target) {
            return isInvalidClick(target, INTERNAL_TIME);
        }
    
        /**
         * Whether this click event is invalid.
         *
         * @param target       target view
         * @param internalTime the internal time. The unit is millisecond.
         * @return true, invalid click event.
         */
        public static boolean isInvalidClick(@NonNull View target, @IntRange(from = 0) long internalTime) {
            long curTimeStamp = System.currentTimeMillis();
            long lastClickTimeStamp = 0;
            Object o = target.getTag(R.id.last_click_time);
            if (o == null){
                target.setTag(R.id.last_click_time, curTimeStamp);
                return false;
            }
            lastClickTimeStamp = (Long) o;
            boolean isInvalid = curTimeStamp - lastClickTimeStamp < internalTime;
            if (!isInvalid)
                target.setTag(R.id.last_click_time, curTimeStamp);
            return isInvalid;
        }
    }
    

    资源目录values下新建资源文件:
    ids.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <item name="last_click_time" type="id"/>
        ...
    </resources>
    

    实现原理:给Button设置名为last_click_time的tag标签并存储上一次点击的时间戳,在一定的时间间隔内只取第一次点击事件。如此, Button会随着界面的销毁而被释放,因而它的名为last_click_time的tag标签存储所占用的内存也会被释放回收。

    使用起来那就是更简单了

            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (AntiShakeUtils.isInvalidClick(v))
                        return;
                    // TODO: 2018/7/1  
                }
            });
    

    你还可以自定义有效点击的时间间隔:

            if (AntiShakeUtils.isInvalidClick(v, 800))
               return;
    
    

    用过之后,从此不罢手!

    篇尾

      QQ:1006368252

    成功的秘诀,在永不改变既定的目的。 —— 卢梭

    相关文章

      网友评论

      • XBaron:AOP才是最优雅的写法哦,一个注解搞定
        https://www.jianshu.com/p/7b354eb8d0d3
        don94:引用了objectBox库再用AOP的话会导致objectBox的一些操作报错,只有用楼主的方法了
      • zbiext:用kotlin写,更优雅~
        SwitchLife:@zbiext kotlin对Android初学者来说不易理解,因为它简写了很多逻辑代码。对于Java老司机来说,kotlin确实是大大提高了开发效率。
      • 七岁就狠拽:如果一个界面里多个按钮, 每个按钮一个跳转, 这个方法能屏蔽么?不如按A跳A页面, 按了A快速按B, 这时候就会出现B页面, 然后回退的时候出现的是A页面, 就不是主页面了
        SwitchLife:此方法并不能解决这个问题。如果要解决这个问题,应该可以考虑从activity层面寻求解决方案!非常感谢你的提问!工作之余,我会考虑这个解决方案的。:smile:
      • 沐小晨曦:其实还有更简单的办法,直接在BaseActivity的dispatchTouchEvent里判断,如果是手指按下&&快速点击直接返回true就好了。这样写不需要每次点击按钮的时候判断了,只需要写一个工具类判断是否是快速点击即可。
        SwitchLife:新发布文章:超级酷炫的Step View:https://www.jianshu.com/p/ccf64bf2e3ed
        SwitchLife:@沐小晨曦 :+1: :+1: :+1:

      本文标题:Android 这才是实现防抖动(防快速点击)的最优雅写法

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