自定义注解处理器生成代码

本文介绍了如何自定义注解处理器在Android项目中生成ButterKnife类似的功能,通过注解处理器在编译时生成findViewById代码,详细阐述了创建AnnotationProcessor Module、定义处理器类、处理注解以及生成代码的过程,并提供了生成目标代码的示例。
摘要由CSDN通过智能技术生成

自定义注解处理器生成代码

先上一段代码:


	public class MainActivity extends AppCompatActivity {
   
	
	    @BindView(R.id.tv)
	    TextView tv;
	    @BindView(R.id.tv2)
	    TextView tv2;
	    @BindView(R.id.tv3)
	    TextView tv3;
	    @Override
	    protected void onCreate(Bundle savedInstanceState) {
   
	        super.onCreate(savedInstanceState);
	        setContentView(R.layout.activity_main);
	        ButterKnife.bind(this);
	        tv.setText(" ViewBinder bindView success!!!");
	    }
	}

  我们经常在项目中使用 ButterKnife 来代替大量的 findViewById(),如上代码所示, 据我所知 ButterKnife 最新版本改用注解处理器来生成 findViewById 代码, 今天我就模仿 ButterKnife 造一个轮子分享给大家, 以及记录下关于注解处理器的相关 API 以供查阅.

(我也是在百度了好多关于注解处理器的博客, 并亲自写了Demo尝试, 啃了好久官方 API 文档, 在此记录共同学习, 希望这篇博客能帮到正在看的你)

  首先明确几个概念:

  • 第一: 注解处理器是由annotationProcessor "com.jakewharton:butterknife-compiler:8.6.0" 在 build.gradle 中配置的内容, 也可以 annotationProcessor project(':AnnotationProcessor') 这样配置本地的工程.

  • 第二: 注解处理器在代码编译时运行运行在操作系统上, 不会随工程打入 APK 中(所以注解处理器工程需要是一个 Java Library).

  • 第三: 注解处理器一般用来生成代码, 实际上也并非很高深, 只是一些陌生的 api 以及通过这些 api 写文件而已.

  说下我的思路, 首先通过注解处理器生成代码(ViewBinding.java), 这些代码处理了 findViewById 的操作, 然后定义一个工具类, 通过反射方式实例化这些生成的代码, 并把 Activity 通过构造方法传给 ViewBinding 以实现 findViewById

  首先新建 AnnotationProcessor Module(Java Library), 需要在build.gradle中配置以下代码:

	dependencies {
	    implementation fileTree(dir: 'libs', include: ['*.jar'])
	    api 'com.google.auto.service:auto-service:1.0-rc3'//必须引用此工程才能正常使用注解处理器
	    api project(':AnnoLib')//Bind.java 注解库
	}

  然后需要定义 MyProcessor 继承 AbstractProcessor, 并实现process方法, 重写init() getSupportedAnnotationTypes() getSupportedSourceVersion() 三个方法, 代码如下所示.

  • getSupportedSourceVersion() 配置 JDK 版本, 写死SourceVersion.latestSupported()就行
  • getSupportedAnnotationTypes() 相当于添加一个注解过滤器, 只有配置了的注解才会走 process() 方法
  • init() 方法用于初始化注解处理器, 需要在此处获取一些工具以供之后在 process() 方法执行时使用.
  • process() 方法需要在此处解析注解, 进行创建文件的操作, 对于参数 RoundEnvironment 我也是知之甚少, 请参见代码中的注释
  • Bind 类在另外一个 Java Moudle 中, 是一个注解:
	
	package annotation;
	
	import java.lang.annotation.ElementType;
	import java.lang.annotation.Retention;
	import java.lang.annotation.RetentionPolicy;
	import java.lang.annotation.Target;
	
	@Retention(RetentionPolicy.SOURCE)
	@Target(ElementType.FIELD)
	public @interface Bind{
   
	    int value();
	}

  • createFile()方法是生成代码的主要逻辑, 生成代码的位置与 使用 Bind 注解 的Activity同一包下 (同包下非 private 变量可以直接访问), 贴下要生成的目标代码:

	package com.eshel.annotationprocessor;
	
	//Auto generated by apt,do not modify!!
	
	public class MainActivity_ViewBinding {
    
	
		public MainActivity_ViewBinding(MainActivity activity){
    
			activity.tv = activity.findViewById(2131165325);
			activity.tv2 = activity.findViewById(2131165325);
			activity.tv3 = activity.findViewById(2131165325);
		}
	}

createFile() 方法就是为了生成上述代码(id 是通过注解拿到的), 假设 MainActivity_ViewBinding 已经生成了, 只需要想办法创建 MainActivity_ViewBinding 对象就可以实现对 MainActivity 中的 View 进行赋值.

MyProcessor 代码如下:


	//必须有此注解
	@AutoService(Processor.class)
	public class MyProcessor extends AbstractProcessor{
   </
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值