android防止按钮连续点击方案之AOP
转载请标明出处http://www.cnblogs.com/yxx123/p/6675567.html
防止连续点击的实现方式有很多种,比如,在所有的onclick里面加上防多次点击的代码,或者定义一个新的OnClickListener,在里面加上防多次点击的代码,然后项目中的所有OnClickListener都用这个listener,当然还有一些其他的方式,这里将介绍一种新的方式来实现,那就是aop。
不知道aop的可以看这篇文章深入理解Android之AOP
在android实现aop通常是用AspectJ来实现,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进行插桩,
@Aspect
public 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: OnClick
04-03 19:41:20.043 5784-5784/ E/MainActivity: execute click
04-03 19:41:20.222 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.377 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.542 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.689 5784-5784/ E/AspectTest: OnClick
04-03 19:41:20.838 5784-5784/ E/AspectTest: OnClick
04-03 19:41:21.012 5784-5784/ E/AspectTest: OnClick
04-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 click
04-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 click
04-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 click
04-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 click
04-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;
}
android防止按钮连续点击方案之AOP的更多相关文章
- Android防止按钮连续点击
为了防止用户或者测试MM疯狂的点击某个button,写个方法防止按钮连续点击. public class Utils { private static long lastClickTime; publ ...
- Android 防止按钮连续点击的方法(Button,ImageButton等)
防止按钮连续点击 其实实现很简单 共通方法 public class Utils { private static long lastClickTime; public static boolean ...
- Runtime应用防止按钮连续点击 (转)
好久之前就看到过使用Runtime解决按钮的连续点击的问题,一直觉得没啥好记录的.刚好今天旁边同时碰到这个问题,看他们好捉急而且好像很难处理,于是我先自己看看… 前面自己也学习了很多Runtime的东 ...
- Android通过AOP实现防止按钮连续点击
防止连续点击的实现方式有很多种,比如,在所有的onclick里面加上防多次点击的代码,或者定义一个新的OnClickListener,在里面加上防多次点击的代码,然后项目中的所有OnClickList ...
- 【Android】按钮点击事件的常用写法
学习总结: 最近学习了Android点击事件的常用写法.点击事件会触发监听对象身上的回调,常用写法有以下四种: 方法一:使用匿名内部类. public class MainActivity exten ...
- Android实现按钮点击效果(第一次点击变色,第二次恢复)
1.首先创建一个按钮 <Button android:id="@+id/click" android:layout_width="fill_parent" ...
- Android Listview中Button按钮点击事件冲突解决办法
今天做项目时,ListView中含有了Button组件,心里一早就知道肯定会有冲突,因为以前就遇到过,并解决过,可惜当时没有记录下来. 今天在做的时候,继续被这个问题郁闷了一把,后来解决后,赶紧来记录 ...
- 关于Android避免按钮重复点击事件
最近测试人员测试我们的APP的时候,喜欢快速点击某个按钮,出现一个页面出现多次,测试人员能不能禁止这样.我自己点击了几下,确实存在这个问题,也感觉用户体验不太好.于是乎后来我搜了下加一个方法放在我们U ...
- android 自定义控件——(五)按钮点击变色
----------------------------------按钮点击变色(源代码下有属性解释)------------------------------------------------- ...
随机推荐
- 关于An internal error occurred during: "Launching MVC on Tomcat 6.x". java.lang.NullPointerException异常处理
一大早上来启动打开myeclipse就报一个这样的错误An internal error occurred during: "Launching MVC on Tomcat 6.x&quo ...
- es6笔记(1) 概要
什么是ES6 ECMAScript 6.0 (简称ES6) 是继ECMAScript 5.1以后的javascript 语言的下一代标准,在2015年6月份发布. 他的目标是使javascript语言 ...
- composer "Failed to decode zlib stream"
dockerFile 中安装composer.... RUN curl -s -f -L -o /tmp/installer.php https://raw.githubusercontent.com ...
- 如何使用jpegtran 压缩JPG图片
说到jpegtran相信很多人都比较陌生,网上相关的资料也很少. jpegtran可以让图片更加的简化,缩小图片的容量,从而增加网络的传输速度.说在多你也不信,下面就让事实证明. 首先下载 jpeg ...
- docker之容器访问和网络连接(三)
前言 当一台服务器上部署了多个应用容器,它们直接可能需要相互通信,比如web应用容器需要访问mysql数据库容器. 主机访问容器 通过映射端口的形式我们可以在外部访问容器内的服务 # 将主机的127. ...
- php扩展Redis功能
php扩展Redis功能 1 首先,查看所用php编译版本V6/V9 在phpinfo()中查看 2 下载扩展 地址:https://github.com/nicolasff/phpredis/dow ...
- Java中抽象类概述
抽象类 1.抽象类的定义 抽象类是为子类提供一个规范,这就必须联系到继承: 抽象类的制定就是让子类继承的: public abstract 类名{ //类体 //抽象方法 修饰符 abstract ...
- idea中搜狗输入法不跟随光标,看不到输入的字
好久没在windows上开发了,今天遇到一个比较坑的问题: 最新版idea,输入法都是最新的;但是idea里面输入字,看不到自己输入的是什么字,好坑... 在外面可以看到输入什么字说明与输入法无关, ...
- linux开启远程访问端口
开启3306端口的tcp访问权限 /sbin/iptables -I INPUT -p tcp -dport 3306 -j ACCEPT 保存防火墙信息 /etc/rc.d/init.d/iptab ...
- PhoneGap学习地址 / PhoneGap API介绍:Events
http://blog.csdn.net/phonegapcn 事件类型: backbutton deviceready menubutton pause resume searchbutton on ...