Android开发一行代码解决安卓重复点击

目录
  • 抛出问题
  • 第一种:弹窗等待
  • 第二种:禁止点击
  • 第三种:时间判断
  • 第四种:AOP实现
  • 封装
  • 总结

抛出问题

“大哥,有个问题想问你!”

“哎,说吧(内心戏:咋又来了。。。准没好事!)”

“我的一个页面中有一个查询按钮,点击就会发出网络请求,等待返回结果后更新数据。”

“这不挺好的嘛!有啥问题啊?”

“对,我也觉得没问题,但测试不按套路出牌啊,测试那边的网络不太好,她点击按钮之后由于网络比较慢就快速多点击了几下,然后。。。”

“然后怎么了?ANR了吧?”

“你咋知道的大哥?”

“来吧,帮您看看吧!”

日常开发中肯定遇到过这种情况,接下来咱们就来看看该怎么解决这种问题。

第一种:弹窗等待

“小子,过来,你看啊,你可以这样,当你点击了按钮之后就弹出一个对话框,设置成不能关闭,等网络请求完成之后再将对话框关闭了就行”

“这是一种方式,但我该怎么写呢?”

“哎,给你写一下例子吧:照着下面代码写就行”

    public void btnDialog(View view) {
        ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("等待");
        progressDialog.setMessage("等待内容");
        //progressDialog.setCanceledOnTouchOutside(false);
        progressDialog.show();
    }

上面代码很简单,这只是一种思路,点击按钮后可以弹出对话框不让用户进行操作(注释的那一行代码就是禁止用户点击的),当请求完成之后再将对话框关闭。

不过不推荐这种做法,官方也不推荐,官方推荐使用ProgressBar。

第二种:禁止点击

“大哥,我觉得弹出对话框不太好,会让用户很反感,还有别的方式吗?”

“行了,早就准备好和你说了,还不止一种呢!这种方式更简单了,只需要设置按钮是否可以点击就行,当用户点击后设置按钮不可点击,请求完成之后再设置可以点击就行了,这个不用我写代码了吧?“

”嘿嘿,这个不用,你刚才说还有好几种,说来听听啊!“

第三种:时间判断

这种方式比上面的稍微麻烦点,但还是很简单。

具体操作就是定义两个变量,一个为上次点击时间,一个为点击的间隔时间。

// 上次点击时间
private long lastClickTime = 0L;
// 两次点击间隔时间(毫秒)
private static final int FAST_CLICK_DELAY_TIME = 1500;

在点击时进行判断就可以了,来看一下代码吧:

public void btnInter(View view) {
  if (System.currentTimeMillis() - lastClickTime >= FAST_CLICK_DELAY_TIME)
     lastClickTime = System.currentTimeMillis();
  }
}

"大哥,这种方法看着比上面两种好用多了,只需要这样定义一下就行了,我就用这一种啊!"

“先别高兴的太早了!”

第四种:AOP实现

“大哥,你刚才说我高兴的太早了是为啥啊?“

”你只有一个页面的话这样写肯定是没有问题的,但是如果有多个页面都有防止按钮重复点击的需求呢?每个页面都定义一遍啊?“

”呃呃,你说的对,大哥,那应该怎么办呢?“

”你知道AOP吗?接下来我要说的就和它有关“

”AOP?那是什么鬼?我知道OOP!“

”不错啊小子,还知道OOP,OOP就是面向对象,而AOP就是面向过程。“

AOP为Aspect OrientedProgramming的缩写,意为面向切面编程。所谓的面向切面编程其实是对业务逻辑又进行了进一步的抽取,将多种业务逻辑中的公用部分抽取出来做成一种服务(比如日志记录,性能统计等),从而实现代码复用。另外这种服务通过配置可以动态的给程序添加统一控制,利用AOP可以对业务逻辑的各个部分进行分离,从而使得业务逻辑各部分之间的耦合度降低。

AOP并不是Android中的产物,而是Java中的,Android官方并没有提供,所以想使用AOP首先要导入可以实现AOP的三方库:

在项目级别的build.gradle中新增以下代码:

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'

然后在moudle的build.gradle中新增依赖:

implementation 'org.aspectj:aspectjrt:1.8.14'

还需要在moudle的build.gradle中最上面添加以下代码:

apply plugin: 'android-aspectjx'

完事之后点击sync Now更新一下。

因为想在所有地方都能使用,所以来定义一个注解:

/**
 * 实现防止按钮连续点击
 * @author jiang zhu on 2020/4/19
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SingleClick {
    /* 点击间隔时间 */
    long value() default 1500;
}

注解大家应该都使用过,运行时就不说了,使用范围定义的是方法上,有一个参数为间隔时间,这个参数意思其实和第三种方案中的类似。

然后就需要定义一个类,里面实现AOP的具体操作:

@Aspect
public class SingleClickAspect {}

然后定义切点,标记切点为所有被@SingleClick的方法:

    @Pointcut("execution(@com.zj.singclick.SingleClick * *(..))")
    public void methodAnnotated() {
    }

这里要注意包名和类名一定要写对。

接下来定义一个切面方法,包裹着切点方法:

    @Around("methodAnnotated()")
    public void aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        View view = null;
        for (Object arg : joinPoint.getArgs()) {
            if (arg instanceof View) {
                view = (View) arg;
                break;
            }
        }
        if (view == null) {
            return;
        }
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (!method.isAnnotationPresent(SingleClick.class)) {
            return;
        }
        SingleClick singleClick = method.getAnnotation(SingleClick.class);
        if (!isFastDoubleClick(view, singleClick.value())) {
            joinPoint.proceed();
        }
    }

来简单分析下,首先看注解中定义了刚才定义的切点方法,然后取出方法的参数,再取出方法的注解,然后调用

isFastDoubleClick方法判断是否为快速点击事件,如果是什么都不干,如果不是则执行原方法中的内容。

下面贴一下isFastDoubleClick方法的代码:

    private static long mLastClickTime;
    private static int mLastClickViewId;
    private static boolean isFastDoubleClick(View v, long intervalMillis) {
        int viewId = v.getId();
        long time = System.currentTimeMillis();
        long timeInterval = Math.abs(time - mLastClickTime);
        if (timeInterval < intervalMillis && viewId == mLastClickViewId) {
            return true;
        } else {
            mLastClickTime = time;
            mLastClickViewId = viewId;
            return false;
        }
    }

上面代码采用了View的id和间隔时间双重判断,即使一个页面的多个按钮都可区分。

“大哥,停停停,都给我说懵了,这写完这个该怎么用啊!”

“别着急,下面就教你该怎么使用!”

使用很简单,只需要在点击时间方法上加上咱们自定义的注解就行了,还可以设置间隔时间,如果不写的话就是默认值,上面也写了,默认值就是1500毫秒。

    @SingleClick(2000)
    public void btnAop(View view) {
        ToastUtils.showShort("btnAop");
        Log.e(TAG, "btnAop");
    }

“是不是很简单啊?”

“大哥,我也不想写这一大堆,我只想用,你能封装成一个库吗?我用的时候直接调用就行!”

“哎,行吧,我封装一下。。。。”

封装

“我已经将上面第四种方式封装为了一个库并上传到了JitPack库,下面给你说一下使用方法吧!”

使用方法很简单,需要几步配置,配置完成之后直接添加注解即可使用,下面是配置方法: 1、在项目的build.gradle中的buildscript中的dependencies添加:

 dependencies {
        ...
        classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'
 }

2、在项目的build.gradle中的allprojects中的repositories添加:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

3、在app的build.gradle中的最上面添加

apply plugin: 'android-aspectjx'

4、在app的build.gradle中的dependencies添加

implementation 'com.github.zhujiang521:AndroidAOP:1.0.1'

5、在你需要使用的方法上面添加上注解即可:

    @SingleClick(2000)
    public void btnAop(View view) {
        ToastUtils.showShort("btnAop");
        Log.e(TAG, "btnAop");
    }

“小子,会用了吗?”

”对了大哥,我的项目中用的是Kotlin啊,我看你写的都是Java,我那里面能用嘛!”

“吆喝,还Kotlin呢,放心吧,一样使用!”

		@SingleClick
    override fun onClick(v: View?) {
        if (v != null) {
            when(v.id){
                R.id.btnClick ->{
                    ToastUtils.showShort("哈哈哈")
                    Log.e("哈哈哈","wwww")
                }
            }
        }
    }

总结

“这回可以了吧?”

“可以了大哥,嘿嘿,感谢大哥”

“小子,快去改项目吧!”

最后放一下项目的地址:https://github.com/zhujiang521/AndroidAOP

以上就是Android开发一行代码解决安卓重复点击的详细内容,更多关于Android开发重复点击的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android开发教程之如何屏蔽View的重复点击

    前言 android 防止重复点击是一个非常常见的需求,每个人都有各自的点击事件的处理习惯,有的喜欢使用匿名内部类,有的activity.fragment.自定义View等继承点击事件然后在onClick()方法中根据id用switch实现各自View的点击事件. 在开发中我们经常需要这样的需求,比如一个验证码发送按钮,我们只想让它响应500毫秒中的第一次点击事件,该如何处理呢?你可能会说这个简单,在点击事件中获取当前时间与上次的比较下,如果小于500毫秒就return掉.是的,这样可以解决,但

  • Android中如何优雅的处理重复点击实例代码

    问题 有时候有些操作是防止用户在一次响应结束中再响应下一个.但有些测试用户就要猛点,狂点.像这种恶意就要进行防止. 比如在客户端中,一些按钮一般是需要避免重复点击的,比如:购买丶支付丶确定丶提交丶点赞丶收藏等等场景,这些场景短时间内的重复点击会引发一些问题. 下面话不多说了,来一起看看详细的介绍吧 以前的处理方式 可能是采用手动记录最后的点击时间,再通过计算时间间隔来判断是否重复点击 private long mLastClickTime = 0; public static final int

  • Android防止按钮重复点击示例代码

    本文中我将介绍一下我自己封装的一个小的工具类库:按钮点击事件类库. 作用:该类库可以防止按钮重复点击,可以判断网络状态,可以判断用户登录状态,以及自定义验证条件等等. 说明:其实现的核心原理就是通过自定义实现自身的OnClickListener类,并重写其中的onClick方法,在onClick方法中执行相应的判断逻辑之后回调我们自定义的抽象方法. 具体效果如下图所示: 使用方式 屏蔽多次点击事件 /** * 测试快速点击事件 */ fastButton.setOnClickListener(n

  • Android优雅地处理按钮重复点击的几种方法

    App中,有很大一部分场景是点击按钮,向服务端提交数据,由于网络请求需要时间,用户很可能会多次点击,造成数据重复提交,造成各种莫名其妙的问题. 因此,防止按钮多次点击,是Android开发中一个很重要的技术手段. 以前的处理方式 网上查找到的,或者你可能会想到的方法大概有这些: 1.每个按钮点击事件中,记录点击时间,判断是否超过点击时间间隔 private long mLastClickTime = 0; public static final long TIME_INTERVAL = 1000

  • Android如何优雅的处理重复点击

    目录 之前的处理方式 现在的处理方式 其他场景处理重复点击 间接设置点击 富文本 列表 数据绑定 总结 项目地址 一般手机上的 Android App,主要的交互方式是点击.用户在点击后,App 可能做出在页面内更新 UI.新开一个页面或者发起网络请求等操作.Android 系统本身没有对重复点击做处理,如果用户在短时间内多次点击,则可能出现新开多个页面或者重复发起网络请求等问题.因此,需要对重复点击有影响的地方,增加处理重复点击的代码. 之前的处理方式 之前在项目中使用的是 RxJava 的方

  • Android中AOP的应用实践之过滤重复点击

    前言 大家对AOP应该都不陌生, 就算没有用过也肯定听说过,切面编程一直是一个热点的话题,AOP即Aspect Oriented Programming的缩写,习惯称为切面编程;与OOP(面向对象编程)万物模块化的思想不同,AOP则是将涉及到众多模块的某一类问题进行统一管理,AOP的优点是将业务逻辑与系统化功能高度解耦,让我们在开发过程中可以只专注于业务逻辑,其他一些系统化功能(如路由.日志.权限控制.拦截器.埋点.事件防抖等)则由AOP统一处理; AspectJ简介 AOP是一种编程思想,或者

  • Android开发一行代码解决安卓重复点击

    目录 抛出问题 第一种:弹窗等待 第二种:禁止点击 第三种:时间判断 第四种:AOP实现 封装 总结 抛出问题 “大哥,有个问题想问你!” “哎,说吧(内心戏:咋又来了...准没好事!)” “我的一个页面中有一个查询按钮,点击就会发出网络请求,等待返回结果后更新数据.” “这不挺好的嘛!有啥问题啊?” “对,我也觉得没问题,但测试不按套路出牌啊,测试那边的网络不太好,她点击按钮之后由于网络比较慢就快速多点击了几下,然后...” “然后怎么了?ANR了吧?” “你咋知道的大哥?” “来吧,帮您看看

  • Android 开发 使用WebUploader解决安卓微信浏览器上传图片中遇到的bug

    先给大家分析下微信浏览器上传图片bug的原因 微信在新版本中采用的是自己的X5内核浏览器,而在较老的版本中还有可能是安卓的原生浏览器.具体的环境我也不太了解,但是经过实际多台安卓机型的测试,我采取的方案可以基本确保在安卓机中微信浏览器的成功上传.苹果机型没问题,因为微信的ios客户端使用的是Safari的内核,没有各种坑,且效果最好. 这里给出一个 WebUploader 官方关于移动端适配的 issues 链接.里面提供的方法确实有效,但就是解决的方案并没有很清楚的展示出来,从该issues中

  • Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题

    前言 之前在做一个Viewpager上面加载多个Fragment时总会实例化已经创建好的Fragmnet对象类似 viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { switch(position){ case 0: fragments=new Fragmnet01(); break; case

  • 实例详解Android解决按钮重复点击问题

    为了防止用户或者测试MM疯狂的点击某个button,写个方法防止按钮连续点击.具体实例代码如下所示: public class BaseActivity extends Activity { protected boolean isDestroy; //防止重复点击设置的标志,涉及到点击打开其他Activity时,将该标志设置为false,在onResume事件中设置为true private boolean clickable=true; @Override protected void on

  • Python一行代码解决矩阵旋转的问题

    今天刷<剑指offer>的时候碰到这样一道题: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10. 思路:可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作,例如 : 1 2 3 4 5 6 7 8 9 利用pop输出并且删除第一行后,再进行一次逆时针旋转,就变成: 6 9

  • Android 开发与代码无关技巧详解

    目录 1.如何找到代码 (1)无敌搜索大法 (2)log输出大法 (3)profiler查看大法 (4)万能法找到页面 2.如何解决bug (1)先看再想最后动手 (2)改变现状 (3)是技术问题还是业务问题 (4)张张嘴远胜于动动手 (5)bug解决不了,那就解决提出bug的人 (6)解决了bug之后 3.如何实现不会的功能 (1)不要急着拒绝 (2)大事化小小事化了 心态要稳,天塌了有个高的顶着 1.如何找到代码 作为客户端的开发,工作中经常遇到,后端的同事来帮忙找接口详情.产品经理来询问之

  • 使用spring-cache一行代码解决缓存击穿问题

    目录 引言 正文 目前缺陷 真正方案 缓存穿透 缓存击穿 缓存雪崩 文末 引言 今天,重新回顾一下缓存击穿这个问题! 之所以写这个文章呢,因为目前网上流传的文章落地性太差(什么布隆过滤器啊,布谷过滤器啊,嗯,你们懂的),其实这类方案并不适合在项目中直接落地. 那么,我们在项目中落地代码的时候,其实只需要一个注解就能解决这些问题,并不需要搞的那么复杂. 本文有一个前提,读者必须是java栈,且是用Springboot构建自己的项目,如果是go技术栈或者python技术栈的,可能介绍的思路仅供大家参

  • 一行代码解决 perl输入 排序 输出问题

    先来看基本的方法: 复制代码 代码如下: chomp(@strings=<STDIN>);  @strings=sort @strings;  print "@strings\n."; 上面的三行代码解决的是输入,然后排序,最后将排序后的结果输出的作用. 只用一行代码即完成的写法: 复制代码 代码如下: print sort<STDIN>; 得到相同的结果,相当给力哦.

  • 一行代码解决网站防挂IFRAME木马方案,小鸽子序列(灵儿)

    最近公司和好朋友的网站纷纷被IFRAME了,有的挂上了鸽子,有的疯狂地弹窗,有的给人家增加流量.一个个文件去查找替换那些IFRAME代码,刚松口气,不久又加上去了,哎,什么世道!于是他们向我这个"JS高手"(他们强加给我的)求救,我也不能等闲视之,只好击键杀杀杀了. 因为FF(Firefox)不怕IFRAME,于是就拿IE开刀,不知道比尔有没有奖发.我只写了一句代码,就搞定了,哈,痛快.就是IE only(特有的)的CSS中的属性expression,插进去试试,果然那些IFRAME不

随机推荐