博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android防止按钮连续点击方案之AOP
阅读量:4648 次
发布时间:2019-06-09

本文共 6693 字,大约阅读时间需要 22 分钟。

转载请标明出处

防止连续点击的实现方式有很多种,比如,在所有的onclick里面加上防多次点击的代码,或者定义一个新的OnClickListener,在里面加上防多次点击的代码,然后项目中的所有OnClickListener都用这个listener,当然还有一些其他的方式,这里将介绍一种新的方式来实现,那就是aop。

不知道aop的可以看这篇文章

在android实现aop通常是用AspectJ来实现,AspectJ的用法可以看这篇文章.

使用OnClickLitener的代码

public class MainActivity extends AppCompatActivity {    final String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.e(TAG, "execute click");            }        });    }}

首先定义一个防止多次点击的工具类

public class NoDoubleClickUtils {    private static long lastClickTime = 0;    private final static int SPACE_TIME = 500;    public synchronized static boolean isDoubleClick() {        long currentTime = System.currentTimeMillis();        boolean isClick2;        if (currentTime - lastClickTime >                SPACE_TIME) {            isClick2 = false;        } else {            isClick2 = true;        }        lastClickTime = currentTime;        return isClick2;    }}

然后使用AspectJ对OnclickLitener进行插桩,

@Aspectpublic class AspectTest {    final String TAG = AspectTest.class.getSimpleName();    @Around("execution(* android.view.View.OnClickListener.onClick(..))")    public void onClickLitener(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        Log.e(TAG, "OnClick");        if (!NoDoubleClickUtils.isDoubleClick()) {            proceedingJoinPoint.proceed();        }    }}

运行程序,多次点击按钮后,log如下

04-03 19:41:20.043 5784-5784/ E/AspectTest: OnClick04-03 19:41:20.043 5784-5784/ E/MainActivity: execute click04-03 19:41:20.222 5784-5784/ E/AspectTest: OnClick04-03 19:41:20.377 5784-5784/ E/AspectTest: OnClick04-03 19:41:20.542 5784-5784/ E/AspectTest: OnClick04-03 19:41:20.689 5784-5784/ E/AspectTest: OnClick04-03 19:41:20.838 5784-5784/ E/AspectTest: OnClick04-03 19:41:21.012 5784-5784/ E/AspectTest: OnClick04-03 19:41:21.158 5784-5784/ E/AspectTest: OnClick

通过log可以看出onClickLitener执行了多次,但使用clcik的的地方只执行了一次。这样,就可以在不改变原来代码的情况下,实现防止连续点击的功能。

但是当又有需求:要求部分按钮是可以连续点击的,该怎么办能?这个时候只要加个注解文件就好。

首先定义个注解

@Retention(RetentionPolicy.CLASS)@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})public @interface DoubleClick {}

并且修改之前的AspectTest文件

private boolean canDoubleClick = false;    private View mLastView;    @Before("@annotation(com.kun.aspectjtest.aspect.DoubleClick)")    public void beforeEnableDoubleClcik(JoinPoint joinPoint) throws Throwable {        canDoubleClick = true;    }    @Around("execution(* android.view.View.OnClickListener.onClick(..))  && target(Object) && this(Object)")    public void OnClickListener(ProceedingJoinPoint joinPoint) throws Throwable {        Object[] objects = joinPoint.getArgs();        View view = objects.length == 0 ? null : (View) objects[0];        Log.e(TAG, "OnClick:" + view);        if (view != mLastView || canDoubleClick || !NoDoubleClickUtils.isDoubleClick()) {            joinPoint.proceed();            canDoubleClick = false;        }        mLastView = view;    }

现在只要在可以连续点击的按钮的onclick前加一个@DoubleClick的注解就好,将MainActivty修改如下

public class MainActivity extends AppCompatActivity {    final String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.e(TAG, "text execute click");            }        });        findViewById(R.id.text2).setOnClickListener(new View.OnClickListener() {            @DoubleClick            @Override            public void onClick(View v) {                Log.e(TAG, "text2 execute click");            }        });    }}

运行程序,分别连续点击第一个view和第二个view,log如下

04-03 23:18:25.598 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{967c04b V.ED..C.. ...P.... 427,579-652,636 #7f0b005d app:id/text}04-03 23:18:25.598 2965-2965/ E/MainActivity: text execute click04-03 23:18:25.768 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{967c04b V.ED..C.. ...P.... 427,579-652,636 #7f0b005d app:id/text}04-03 23:18:25.941 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{967c04b V.ED..C.. ...P.... 427,579-652,636 #7f0b005d app:id/text}04-03 23:18:26.113 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{967c04b V.ED..C.. ...P.... 427,579-652,636 #7f0b005d app:id/text}04-03 23:18:29.473 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{2c5ea28 V.ED..C.. ...P.... 427,936-652,993 #7f0b005e app:id/text2}04-03 23:18:29.473 2965-2965/ E/MainActivity: text2 execute click04-03 23:18:29.644 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{2c5ea28 V.ED..C.. ...P.... 427,936-652,993 #7f0b005e app:id/text2}04-03 23:18:29.644 2965-2965/ E/MainActivity: text2 execute click04-03 23:18:29.801 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{2c5ea28 V.ED..C.. ...P.... 427,936-652,993 #7f0b005e app:id/text2}04-03 23:18:29.801 2965-2965/ E/MainActivity: text2 execute click04-03 23:18:29.965 2965-2965/ E/AspectTest: OnClick:AppCompatTextView{2c5ea28 V.ED..C.. ...P.... 427,936-652,993 #7f0b005e app:id/text2}04-03 23:18:29.965 2965-2965/ E/MainActivity: text2 execute click

可以发现第一个view不能被连续点击了,但第二个可以连续点击。

如果项目里用了butterknife,需要修改execution语句,改为

(execution(* android.view.View.OnClickListener.onClick(..))||execution(* butterknife.internal.DebouncingOnClickListener.doClick(..)))  && target(Object) && this(Object)

并且在build.gradle文件中加入过滤

aspectjx {    includeJarFilter 'butterknife'//织入遍历butterknife    excludeJarFilter '.jar'//忽略所有依赖的库}

代码如下:

private boolean canDoubleClick = false;    @Around("@annotation(com.kun.aspectjtest.aspect.DoubleClick)")    public void beforeEnableDoubleClcik(JoinPoint joinPoint) throws Throwable {        canDoubleClick = true;    }    private View mLastView;    @Around("(execution(* android.view.View.OnClickListener.onClick(..))||execution(* butterknife.internal.DebouncingOnClickListener.doClick(..)))  && target(Object) && this(Object)")    public void OnClickListener(ProceedingJoinPoint joinPoint) throws Throwable {        Object[] objects = joinPoint.getArgs();        View view = objects.length == 0 ? null : (View) objects[0];        Log.e(TAG, "OnClick:" + view);        if (view != mLastView || canDoubleClick || !NoDoubleClickUtils.isDoubleClick()) {            joinPoint.proceed();            canDoubleClick = false;        }        mLastView = view;    }

转载于:https://www.cnblogs.com/yxx123/p/6675567.html

你可能感兴趣的文章
Netty4.x中文教程系列(四) 对象传输
查看>>
linux下find命令使用举例、
查看>>
GET请求在Tomcat中的传递及URI传递
查看>>
ubuntun 服务器与Mac
查看>>
重温JSP学习笔记--与日期数字格式化有关的jstl标签库
查看>>
java-Date-DateFormat-Calendar
查看>>
封装CLLocationManager定位获取经纬度
查看>>
我的第一篇博客-(Eclipse中或Myeclipse中如果不小心删除了包那可怎么办?)
查看>>
对easyui datagrid组件的一个小改进
查看>>
类似以下三图竞争关系的IT企业
查看>>
清明节
查看>>
ubuntu如何安装svn客户端?
查看>>
javascript之非构造函数的继承
查看>>
C#实现 单点登录(SSO)
查看>>
高精度计算(2015.8.1)
查看>>
cocos2d-x tile map瓦片地图的黑线及地图抖动解决方案
查看>>
软工网络15团队作业2——团队计划
查看>>
Android屏幕适配
查看>>
ps简单操作文档
查看>>
CSS之float样式
查看>>