| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 如何在-Android-中完成一个-APT-项目的开发?,挑战大厂重燃激情 -> 正文阅读 |
|
[移动开发]如何在-Android-中完成一个-APT-项目的开发?,挑战大厂重燃激情 |
Intent intent = new Intent(context, TestActivity.class); 以及在TestActivity中的获取数据操作: id = intent.getIntExtra(“id”, 0); 以上代码的问题在于,对于每个过程都需要编写类似的代码,重复性比较大,浪费时间。 在数据传递和解析时,key需要保持一致。我们可以用常量来代替,但将定义很多常量。 我们希望以上代码可以自动化生成,开发者只需要调用几个可读性更好的方法,即可实现上述过程。 ####2.分析 针对这个需求场景,我们需要实现的自动化功能如下: (1)自动为TestActivity生成一个类,叫做TestActivityFastBundle; 我们期望简化后调用时候是这样的,这将跳转到TestActivity: new TestActivityFastBundle() 在TestActivity中,我们期望调用: new?TestActivityFastBundle().bind(this,?getIntent()); 实现自动将Intent中的变量赋值给当前类中的变量。 ###搭建APT项目 1.创建一个Android Library,并创建自己需要的注解类。 举例: @Retention(CLASS) 2.创建一个Java Library,引用步骤1中所创建的Android Library,并为这个Java Library添加依赖。 implementation?‘com.google.auto.service:auto-service:1.0-rc2’ 介绍一下这个库是做什么用的: 因为注解处理器是在编译期间进行工作,需要向编译器进行“注册”,让编译器知道需要使用哪个注解器处理数据。 如果不使用auto-service库,那么手动注册的方法如下: 1.在Library中创建resources文件夹; 3.创建自己的处理类,继承AbstractProcessor,并使用auto-service注册。 举例: @AutoService(Processor.class) 在创建AbstractProcessor子类后,我们需要重写其中的几个方法,来实现自己的处理逻辑: @Override Processor的初始化方法,在编译阶段会首先回调此方法,ProcessingEnvironment类包含了解析需要的数据对象,我们可以通过它获取到一系列我们需要的其他对象,进而获取到需要的数据。 @Override process方法在编译过程中回调,在此我们可以获取到我们需要的类、对象及其对应的注解,在此可以分析并处理数据,最终生成我们需要的代码。 @Override getSupportedAnnotationTypes方法帮助我们获得所需要的注解类。我们将自己需要的类名放入Set中并返回给注解处理器,换句话说,在这里为注解处理器指定需要处理哪些注解。 4.在项目中引用 在主项目的gradle中引用包含注解的Android Library引用注解器所在的Java Library。由于kotlin的引入,建议使用kapt而非annotationProcessor。 举例: kapt?project(’:libProce’)
至此,工程整体结构已经搭建完成。 后续将介绍APT中各种类和对象的作用,以及如何实现我们需要的功能。 ###APT中的数据类型与概念 ####1.ProcessingEnvironment 当我们在子类中复写了AbstractProcessor的init方法时,其参数就是一个ProcessingEnvironment对象。它内部提供了实用的对象,如Elements、Types、Filer,在APT过程中都具有重要作用。我们可以获取到这些对象,来实现我们需要的功能。 ####2.Element 在APT阶段,任何事物都被称为元素。比如一个对象、一个类、一个方法、一个参数。在APT中,它们都被统一称为元素。Element本身是一个接口,也有多个子类,比如TypeElement、VariableElement,子类在其基础上增加了额外的接口方法来描述具体事物的特殊属性。 ####3.ElementKind 由于在APT中,任何事物都被称为元素,所以我们需要知道某个元素究竟是什么,这时候可以通过ElementKind判断。 ElementKind是一个枚举类。其中包括但不限于PACKAGE(包)、CLASS(类)、INTERFACE(接口)、FIELD(变量)、PARAMETER(参数)、METHOD(方法)等。这些都是我们开发中的基本概念。 ####4.Elements Elements可以理解为一个工具类,它的功能就是操作Element对象,对Element对象进行一些处理或取值。 ####5.TypeElement TypeElement是Element子类,它表示这个元素是一个类或者接口。当Element满足条件时候,可以强转为一个TypeElement对象。 ####6.VariableElement VariableElement是Element子类,它表示这个元素是一个变量、常量、方法、构造器、参数等。当Element满足条件时候,可以强转为一个VariableElement对象。 ####7.Filer Filer是一个文件操作的接口,它可以创建或写入一个Java文件。主要针对的是Java文件对象,和一般文件的区别在于这是专门处理Java类文件的,以.java或.class为后缀的文件。在APT过程中,如果我们自动化代码生成完毕,需要生成一个.java或.class文件的时候,就需要用到Filer。 ####8.Name Name类是CharSequence的子类,主要表示类名、方法名。大部分情况下可以认为它和String等价。 ####9.Types Types可以理解为一个工具类,是类型操作工具,在APT阶段,我们需要知道一个变量是int还是boolean,那将需要通过Types相关类处理。它可以操作TypeMirror对象。 ####10.TypeMirror TypeMirror表示数据类型。比如基本类型int、boolean,也可以表示复杂数据类型,比如自定义类、数组、Parcelable等。 ####11.Modifier 即修饰词。比如声明一个变量时候,private static final这些均为修饰词。大部分被Android Studio标示为蓝色的都是修饰词(除了class int interface这些)。 注:如果一个类中的变量缺省作用范围,那么修饰词为default。 ####12.RoundEnvironment 当我们在子类中复写了AbstractProcessor的process方法时,其参数就是一个RoundEnvironment对象。可以通过RoundEnvironment对象获取到我们在代码中设置了相关注解的Element。 ###APT处理过程拆解 下面将以上文中所举出的场景,逐步对APT处理过程进行拆解,最终获取到我们需要的属性,为生成自动化代码做准备。 在TestActivity中的变量上设置注解: @AutoBundle 其中AutoBundle注解是我们自己定义的注解类。 初步设计好后,我们需要在process方法中重写我们的逻辑: @Override 第一步: 获取所有被AutoBundle注解所声明的元素。这里我们知道,其实只有三个变量; for (Element element : roundEnvironment.getElementsAnnotatedWith(AutoBundle.class)) { } 第二步: 对每个循环中的Element对象,获取其数据信息; if (element.getKind() == ElementKind.FIELD) { variableElement中包含的数据包括修饰词、类型、变量名等; typeElement中包含的数据包括类名、包名等。 // 获取类名 // 获取包名 // 获取变量上的注解信息 // 获取变量名 // 获取变量类型 对于我们上文定义的某个变量,比如: @AutoBundle(require = true) 那么获取到数据后: require = true 其他两个变量同理。 三次循环将获取到我们需要的所有信息。 包括三个变量的注解值、变量名、类型。同时我们也获取到了TestActivity的类名和包名。可以对这些数据进行一些封装和缓存。接下来就可以自动化生成代码了。 我将上述变量值封装为ClassHoder与FieldHolder类中,ClassHolder保存了类名、包名等信息,FieldHolder保存了每个变量类型、变量名、注解等信息。下面将用这些保存好的数据,通过JavaPoet生成代码。 ###JavaPoet代码自动化生成 JavaPoet是Java代码自动生成框架,是一个github上的开源项目,地址:https://github.com/square/javapoet 。 JavaPoet简化了Java代码生成的开发难度,通过建造者模式,使调用更加人性化,可读性提升。具有自动import的功能,不需要再手动指定。 JavaPoet中,大部分数据类型使用了APT中通用的类型,结合APT自动化产生代码非常方便快速。 1.TypeSpec.Builder TypeSpec.Builder是类的构建类,这里的类是广义上的,可以是一个class、interface、annotation等。 示例代码: TypeSpec.Builder?contentBuilder?=?TypeSpec.classBuilder(“yourClassName”) 2.MethodSpec.Builder MethodSpec.Builder是方法的构建类。 示例代码: MethodSpec.Builder bindMethodBuilder = MethodSpec.methodBuilder(“yourMethodName”) 3.FieldSpec.Builder FieldSpec.Builder是变量的构建类。 示例代码: FieldSpec.Builder fieldBuilder = FieldSpec.builder(ClassName.get(field.getType()), “yourFieldName”, Modifier.PRIVATE) 4.JavaFile.Builder 示例代码: JavaFile javaFile = JavaFile.builder(classHolder.getPackageName(), contentBuilder.build()) 5.各类Builder的方法 6.代码生成示例 构造代码与生成结果示例1: for (FieldHolder field : fields) { private int id; 5.各类Builder的方法 [外链图片转存中…(img-n3fKWsqv-1640253709108)] 6.代码生成示例 构造代码与生成结果示例1: for (FieldHolder field : fields) { private int id; |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 10:42:44- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |