Android Gradle Plugin的应用

背景:

1.趋势:目前很多知名框架在后期维护中基于性能优化,代码解耦的考虑都加入Gradle Plugin的技术,如Alibaba的ARouter, 360的Replugin等等。在后期的版本升级后,在性能上都有很大的优化。

2.需求:随着项目中对于APM(Application Performance Management) 越来越关注,后期功能上会加入性能监控,网络请求耗时等一些监控,这个时候为了减少对原业务功能的影响,​达到“无需修改原有结构,无侵入接入”和“无性能损害”的目标,就需要有一种办法在编译阶段自动插入代码实现(运行阶段操作肯定会消耗性能,pass)。那就是传说中的“插桩”,AOP思想(面向切面编程),使用Gradle Plugin 技术。

3.现状:产品经理为了对产品上线之后用户操作数据的统计,每次上线前会对代码中增加埋点。随着功能的庞大和业务的复杂,造成埋点代码越来越多,这些代码在某种程度会影响业务逻辑的阅读。这个时候如果能把埋点代码和业务代码进行分离,只要在编译的时候把埋点代码注入到业务代码就可以了。

概述

Gradle Plugin是Android项目中为了达到优化性能,代码解耦的目标,在编译阶段通过字节码的改变在已存在的类中插入代码,或者创建一个新的类,采用的是AOP面向切面思想编程,接下来以下几个方面进行讲述:

1.Android App的编译过程

2.自定义Gradle Plugin的创建和Transform api的使用

3.使用asm实现字节码插桩

编译过程

编译过程

上图介绍了一个app是如何编译成在手机上运行的apk,gradle plugin 是在生成.class文件之后,生成.dex之前对字节码进行操作。它其中包含.class 文件和第三方的jar文件,在编译过程中遍历拿到这些文件,然后对需要更改的类文件进行更改。

自定义Gradle-Plugin 插件

1.自定义插件

   1.首先引入jar包:

     2.0.0以前:

compile'com.android.tools.build:transform-api:1.5.0'

     2.0.0以后:

//从2.0.0版本开始就是在gradle-api中

implementation'com.android.tools.build:gradle-api:3.1.4

    2.创建自定义插件:

     首先创建自定义插件,在自定以插件中注册一个自定义的transform,编写语言可以是groovy,java,kotlin

Arouter 创建的自定义插件

如上图apply方法中只有在主app中才会需要导入这个插件生成注册的代码。然后创建自定义RegisterTransform 注册到插件中,其中创建了一个集合,赋值给这个插件,这个会在后面讲解。

2自定义transform

1.transform原理及应用

transform原理

    1.每一个transform 是一个Gradle task,TaskMandger 会把Transform 串联起来,第一个 Transform 会把javac编译的class文件,jar包,resource(asset中的资源)接收到,然后进行处理,传送给下一个Transform。

     2.自定义的transform会插到系统自带的前面。

      3.dexBuilder,dexMerger,mergeJavaRes,mergeJniLibs,proguard 这些常见Transform都属于系统的Transform。

2.transform类详解


自定义Transform

1.getName:返回插件的名字,这个 name 并不是最终的名字, 

        格式如:transformClassesWith“name”ForDebug

2.getInputTypes: 获取过滤的类型:

       CONTENT_CLASS:表示要处理编译后的字节码,可能是 jar 包也可能是目录

       CONTENT_RESOURCES:表示处理标准的 java 资源,在assert文件夹中

3.getScopes:获取过滤的范围

        PROJECT: 只处理当前项目

        SUB_PROJECTS:只处理子项目

        PROJECT_LOCAL_DEPS:只处理当前项目的本地依赖,例如jar, aar

        EXTERNAL_LIBRARIES:只处理外部的依赖库

        PROVIDED_ONLY:只处理本地或远程以provided形式引入的依赖库

       TESTED_CODE:测试代码

4 isIncremental: 当前 Transform 是否支持增量编译

        NOTCHANGED: 当前文件不需处理,甚至复制操作都不用;

        ADDED、CHANGED: 正常处理,输出给下一个任务;

        REMOVED: 移除outputProvider获取路径对应的文件。

5:transform()方法的参数详解

       inputs :消费型输入

       referencedInputs:引用型输入,无需输出 

       isIncremental:是否增量更新

       outputProvider:管理输出路径

6. transform 的优化:

private  WaitableExecutor waitableExecutor;

waitableExecutor =WaitableExecutor.useGlobalSharedThreadPool();
//异步并发处理jar/class

waitableExecutor.execute(()->{

        bytecodeWeaver.weaveJar(srcJar,destJar);returnnull;
});

//异步并发处理jar/class
waitableExecutor.execute(()->{
        bytecodeWeaver.weaveSingleClassToFile(file,outputFile,inputDirPath);returnnull;
});
//等待所有任务结束
waitableExecutor.waitForTasksWithQuickFail(true);

3.ASM使用

简介:

     ASM 可以直接产生二进制的class 文件,也可以在增强既有类的功能。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。

ASM框架中的核心类有以下几个:

        ClassReader:该类用来解析编译过的class字节码文件。

        ClassWriter:该类用来重新构建编译后的类,比如说修改类名、属性以及方法,甚至可以生成新的类的字节码文件。

        ClassVisitor:主要负责 “拜访” 类成员信息。其中包括标记在类上的注解,类的构造方法,类的字段,类的方法,静态代码块。

        AdviceAdapter:实现了MethodVisitor接口,主要负责 “拜访” 方法的信息,用来进行具体的方法字节码操作。


  ClassVisitor 实现


MethodVisitor 实现

总结:Android Gradle Plugin 大概讲到这,最后一步Asm实现可以使用Android studio 插件asm-bytecode-outline,它会生成asm实现代码。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容