Android深思如何防止快速点击_android 避免列表快速点击

本文介绍了在Android开发中如何使用RxJava或KotlinFlow实现简单快速点击防止,以及通过拦截事件和方法来确保功能的灵活性。作者还讨论了FastClickHelper类中的解决方案,并强调了成为Android架构师需要的知识体系和实践技巧。
摘要由CSDN通过智能技术生成

3. 流

简单来说也有很多人用了Rxjava或者kotlin的flow去实现,像这种实现也就是能方便而已,在底层上并没有什么实质性的突破,所以就不多说了,说白了就是和上面一样。

4. 通过拦截

因为上面已经说了kt的情况,所以接下来的相关代码都会用java来实现。

通过拦截来达到防止快速点击的效果,而拦截我想到有2种方式,第一种是拦截事件,就是基于事件分发机制去实现,第二种是拦截方法。

相对而言,其实我觉得拦截方法会更加安全,举个场景,假如你有个页面,然后页面正在到计算,到计算完之后会显示一个按钮,点击后弹出一个对话框。然后过了许久,改需求了,改成到计算完之后自动弹出对话框。但是你之前的点击按钮弹出对话框的操作还需要保留。那就会有可能因为某些操作导致到计算完的一瞬间先显示按钮,这时你以迅雷不及掩耳的速度点它,那就弹出两次对话框。

(1)拦截事件
其实就是给事件加个判断,判断两次点击的时间如果在某个范围就不触发,这可能是大部分人会用的方式。

正常情况下我们是无法去入侵事件分发机制的,只能使用它提供的方法去操作,比如我们没办法在外部影响dispatchTouchEvent这些方法。当然不正常的情况下也许可以,你可以尝试往hook的方向去思考能不能实现,我这边就不思考这种情况了。

public class FastClickHelper {

    private static long beforeTime = 0;
    private static Map<View, View.OnClickListener> map = new HashMap<>();

    public static void setOnClickListener(View view, View.OnClickListener onClickListener) {
        map.put(view, onClickListener);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                long clickTime = SystemClock.elapsedRealtime();
                if (beforeTime != 0 && clickTime - beforeTime < 1000) {
                    return;
                }
                beforeTime = clickTime;

                View.OnClickListener relListener = map.get(v);
                if (relListener != null) {
                    relListener.onClick(v);
                }
            }
        });
    }

}

简单来写就是这样,其实这个就和上面说的kt的扩展函数差不多。调用的时候就

FastClickHelper.setOnClickListener(view, this);

但是能看出这个只是针对单个view去配置,如果我们想其实页面所有view都要放快速点击,只不过某个view需要快速点击,比如抢东西类型的,那肯定不能防。所以给每个view单独去配置就很麻烦,没关系,我们可以优化一下

public class FastClickHelper {

    private Map<View, Integer> map;
    private HandlerThread mThread;

    public void init(ViewGroup viewGroup) {
        map = new ConcurrentHashMap<>();
        initThread();
        loopAddView(viewGroup);

        for (View v : map.keySet()) {
            v.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        int state = map.get(v);
                        if (state == 1) {
                            return true;
                        } else {
                            map.put(v, 1);
                            block(v);
                        }
                    }
                    return false;
                }
            });
        }
    }

    private void initThread() {
        mThread = new HandlerThread("LAZY_CLOCK");
        mThread.start();
    }

    private void block(View v) {
        // 切条线程处理
        Handler handler = new Handler(mThread.getLooper());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (map != null) {
                    map.put(v, 0);
                }
            }
        }, 1000);
    }

    private void exclude(View... views) {
        for (View view : views) {
            map.remove(view);
        }
    }

    private void loopAddView(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            if (viewGroup.getChildAt(i) instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) viewGroup.getChildAt(i);
                map.put(vg, 0);
                loopAddView(vg);
            } else {
                map.put(viewGroup.getChildAt(i), 0);
            }
        }
    }

    public void onDestroy() {
        try {
            map.clear();
            map = null;
            mThread.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

我把viewgroup当成入参,然后给它的所有子view都设置,因为onclicklistener比较常用,所以改成了设置setOnTouchListener,当然外部如果给view设置了setOnTouchListener去覆盖我这的set,那就只能自己做特殊处理了。
在外部直接调用

FastClickHelper fastClickHelper = new FastClickHelper();
fastClickHelper.init((ViewGroup) getWindow().getDecorView());

要如何成为Android架构师?

搭建自己的知识框架,全面提升自己的技术体系,并且往底层源码方向深入钻研。
大多数技术人喜欢用思维脑图来构建自己的知识体系,一目了然。这里给大家分享一份大厂主流的Android架构师技术体系,可以用来搭建自己的知识框架,或者查漏补缺;

对应这份技术大纲,我也整理了一套Android高级架构师完整系列的视频教程,主要针对3-5年Android开发经验以上,需要往高级架构师层次学习提升的同学,希望能帮你突破瓶颈,跳槽进大厂;

最后我必须强调几点:

1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍理解了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。
2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 最后你达到什么水平取决你消化了多少知识
3.最终你的知识框架应该是一个完善的,兼顾广度和深度的技术体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。

你只需要按照在这个大的框架去填充自己,年薪40W一定不是终点,技术无止境

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值