天天看点

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

一、点击频控常规做

由于历史原因 ,FM项目中存在 多种方式  :

1)调用处分散实现

缺点:代码冗余 ,实现不统一  (如时间间隔频率不一样等等)

2)定义成工具类使用(如下 ClickUtils)

ClickUtils 工具类克服了1)中问题,但是也存在一些问题,如 每个调用处需要手动组合一个tag (一般是文件名+ 方法名 )。

有些人可能会剔除都是点击事件直接用viewId 不就可以了吗 ,如果使用viewId 势必要传一个View 进去,这样大大限制了使用场景 (目前 FM 已经使用DataBinding),这种方式被抛弃。

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图1 ClickUtils 定义

如果想自动化生成tag 也有其他办法 :如 new Throwable().getStackTrace() ,缺点有一定性能损耗。

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图2 通过 StackTrace 获取class 名和 行号

二 、AOP+Annotation 实现

那有没有更简单的方式 去实现  :去冗余 、更简洁自动化  ,对应AOP+Annotation 实现方式应运而生。

原理简单如下 :通过Annotation 标注那些方法需要判断  ,同过AOP 方式找到@SingleClick 使用的切点 ,自动生成唯一的 tag (这里是文件名 + 行号 )

(1)时间间隔定值实现方式

1)Aspect 插件Android gradle 开发环境配置

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图3 Aspect 插件 配置

2)定义@SingleClick注解

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图4 定义@SingleClick注解

3)定义切点处理方法 类 SingleClickAspect

利用joint.S=sourceLocation 获取文件名 和 行号 ,组合成可唯一确认的tag ,到此功能完全实现。

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图5 SingleClickAspect 定义

(2)时间间隔可设方式

1)定义带默认值方法注解

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图6 定义带默认值方法注解

2)对应修改SingleClickAspect修改

由于本次需要获取注解上的设定值 ,因而这里需要使用MethodSignature 方法,对照改写如下,使用方式 @SingleClick  或者@SingleClick(xxx)

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图7 修改后SingleClickAspect 定义

运行发现,Debug 版本没有问题 ,Release 版本 挂掉了 ,报错信息指出 :method 为null 。细想都是按照@SingleClick 注解找的,method 怎么能为空,而且项目中也对所有注解混淆进行了Keep ,因此将问题锁定在AOP 的实现上。

1)使用反编译工具jadx 查看Rebase  和Debug 版本后的代码 与插装之前做对比

观察的是AlbumShowViewModel::onMoreClick()  方法 ,debug 版本如下 :

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图 8 debug 版本插装后的代码

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图 9 release 版本插装后的代码

2)导致method 为null的原因

对比release 版本和debug 版本知 ,插装时使用的是makeMethodSig ,第三个参数declaringType 传的就是class 名字 ,直接使用Class.forName(declaringType) 创建class ,由于插装后 ,release 版本类名混淆,导致这里发生异常 ,method 为null。

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图10 插装实现

3)解决方式

解决方式很简易 :keep 住使用@SingleClick注解的类即可

android 点击频率控制_AOP+Annotation 应用—— 点击频率控制(防止快速点击多次)...

图11  解决方式

综上两种方式问题,FM项目最终选择时间间隔定值方式作为最终方案。