ASM字节码插桩实现点击防抖

2021-08-09  本文已影响0人  HarryChen

关于gradle plugintransform之前的文章说过了,这里就不展开说了
思路:在点击事件onclick的时候,将view的onclick在给定的时间给拦截掉。以前我们可能都是用一个util来拦截,这样在每个点击事件都得去判断,那么这里就用字节码插桩的形式来实现一下。

ASM的引入

dependencies {
    implementation gradleApi()
    implementation localGroovy()
    //常用io操作
    implementation "commons-io:commons-io:2.6"

    // Android DSL  Android编译的大部分gradle源码
    implementation 'com.android.tools.build:gradle:3.6.2'
    implementation 'com.android.tools.build:gradle-api:3.6.2'
    //ASM
    implementation 'org.ow2.asm:asm:7.1'
    implementation 'org.ow2.asm:asm-util:7.1'
    implementation 'org.ow2.asm:asm-commons:7.1'
}
复制代码

常用的对象

ASM工作流程

通过ClassReader读取class字节码文件,然后ClassReader将读取到的数据通过一个ClassVisitor(上面的ClassWriter其实就是一个ClassVisitor)将数据表现出来.表现形式: 将字节码的每个细节按顺序通过接口的方式传递给ClassVisitor.就比如说,访问到了class文件的xx方法,就会回调ClassVisitor的visitMethod方法;访问到了class文件的属性,就会回调ClassVisitor的visitField方法.

ClassWriter是一个继承了ClassVisitor的类,它保存了这些由ClassReader读取出来的字节流数据,最后通过它的toByteArray方法获得完整的字节流

具体代码

主要技术点: Gradle plugin + transform + annotation + ASM

plugin.jpg

[图片上传失败...(image-16cf10-1628517507917)]

process.jpg annotation.jpg classvisit.jpg method.jpg asset.jpg shouldclick.jpg

代码测试

testcode.jpg

反编译查看

result1.jpg result2.jpg result3.jpg

可以看到,正常的onclick写法是可以插桩成功,添加注解时可以成功跳过插桩的,lamda表达式这种情况下是无法插桩成功的,生成的class方法名上没有onclick标志,找不到什么共同点,这个暂时没有想到什么好的办法,但是现在基本都是kotlin代码了,所以这种形式感觉还是有些鸡肋了。
项目源码

上一篇 下一篇

猜你喜欢

热点阅读