Android APT开发教程 四 apt生成代码与所注释元素之间的交互
2018-01-30 19:42
513 查看
github项目代码地址
https://github.com/979451341/TestAPT
怎么配置环境上篇文章说了
http://blog.csdn.net/z979451341/article/details/79126413
我准备写一个apt通过注解给int类型的变量赋值
在annotation中,创建两个注解,为何要有两个呢,第一个是为了获取整个activity的信息,第二个是为了标注需要处理的元素。
@Target(ElementType.TYPE)[url=mailto:br/>@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.CLASS)
}
@Target(ElementType.FIELD)[url=mailto:br/>@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
int value() default 0;
}
我们第一个注释用在类名上面为了获取整个类里面所有的元素,但是可能注释了多个类,roundEnv.getElementsAnnotatedWith返回的是多个类的集合,然后顺序取出类,通过工具类elementUtils.getAllMembers获取类里所有的元素,然后判断是否有注释,如果有做相应处理。
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
接下来说一下如何处理,在取出类A的时候,创建类继承类A并根据类A的名字来取类名,并创建一个函数来获取这个类A的实例,后面在从类A一个一个取出元素的时候判断是否有注解,如果有就在之前的函数里添加一行代码,对类A的元素进行赋值。
完整注解处理器代码如下
@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {
private Elements elementUtils;[url=mailto:br/>@Override
@Override
// 规定需要处理的注解
return Collections.singleton(TestActivity.class.getCanonicalName());[url=mailto:br/>}
@Override
}
@Override
public class MainActivity extends Activity {
}
生成代码如下,生成代码在:app/build/generated/source/apt/下
public final class TestMainActivity extends MainActivity {
public static void setDefualt(MainActivity activity) {
activity.a = 0;
activity.b = 1;
activity.c = 1;
}
}
效果
01-22 15:24:48.712 5647-5647/com.example.zth.myapplication V/zzw: a:0 b:1 c:1
总结
我们使用在类名的注解是为了获取整个类的信息,使用在变量的注解是为了分清哪个元素需要处理,生成的代码则是为了完成实际的业务
https://github.com/979451341/TestAPT
怎么配置环境上篇文章说了
http://blog.csdn.net/z979451341/article/details/79126413
我准备写一个apt通过注解给int类型的变量赋值
在annotation中,创建两个注解,为何要有两个呢,第一个是为了获取整个activity的信息,第二个是为了标注需要处理的元素。
@Target(ElementType.TYPE)[url=mailto:br/>@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.CLASS)
}
@Target(ElementType.FIELD)[url=mailto:br/>@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
int value() default 0;
}
我们第一个注释用在类名上面为了获取整个类里面所有的元素,但是可能注释了多个类,roundEnv.getElementsAnnotatedWith返回的是多个类的集合,然后顺序取出类,通过工具类elementUtils.getAllMembers获取类里所有的元素,然后判断是否有注释,如果有做相应处理。
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(TestActivity.class); for (Element element : elements) { // 判断是否Class TypeElement typeElement = (TypeElement) element; List<? extends Element> members = elementUtils.getAllMembers(typeElement); for (Element item : members) { TestInt diView = item.getAnnotation(TestInt.class); if (diView == null){ continue; } } return true; }
接下来说一下如何处理,在取出类A的时候,创建类继承类A并根据类A的名字来取类名,并创建一个函数来获取这个类A的实例,后面在从类A一个一个取出元素的时候判断是否有注解,如果有就在之前的函数里添加一行代码,对类A的元素进行赋值。
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(TestActivity.class); for (Element element : elements) { // 判断是否Class TypeElement typeElement = (TypeElement) element; List<? extends Element> members = elementUtils.getAllMembers(typeElement); MethodSpec.Builder bindViewMethodSpecBuilder = MethodSpec.methodBuilder("setDefualt") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(TypeName.VOID) .addParameter(ClassName.get(typeElement.asType()), "activity"); for (Element item : members) { TestInt diView = item.getAnnotation(TestInt.class); if (diView == null){ continue; } bindViewMethodSpecBuilder.addStatement(String.format("activity.%s = %s",item.getSimpleName(),diView.value())); } TypeSpec typeSpec = TypeSpec.classBuilder("Test" + element.getSimpleName()) .superclass(TypeName.get(typeElement.asType())) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(bindViewMethodSpecBuilder.build()) .build(); JavaFile javaFile = JavaFile.builder(getPackageName(typeElement), typeSpec).build(); try { javaFile.writeTo(processingEnv.getFiler()); } catch (IOException e) { e.printStackTrace(); } } return true; }
完整注解处理器代码如下
@AutoService(Processor.class)
public class TestProcessor extends AbstractProcessor {
private Elements elementUtils;[url=mailto:br/>@Override
@Override
// 规定需要处理的注解
return Collections.singleton(TestActivity.class.getCanonicalName());[url=mailto:br/>}
@Override
}
@Override
public class MainActivity extends Activity {
@TestInt int a; @TestInt(value = 1) int b; @TestInt(1) int c; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestMainActivity.setDefualt(this); Log.v("zzw"," a:"+a+" b:"+b+" c:"+c); }
}
生成代码如下,生成代码在:app/build/generated/source/apt/下
public final class TestMainActivity extends MainActivity {
public static void setDefualt(MainActivity activity) {
activity.a = 0;
activity.b = 1;
activity.c = 1;
}
}
效果
01-22 15:24:48.712 5647-5647/com.example.zth.myapplication V/zzw: a:0 b:1 c:1
总结
我们使用在类名的注解是为了获取整个类的信息,使用在变量的注解是为了分清哪个元素需要处理,生成的代码则是为了完成实际的业务
相关文章推荐
- Android APT开发教程 四 apt生成代码与所注释元素之间的交互
- Android APT开发教程 五 使用注释完成findViewById和setContentView
- Android APT开发教程 二 JavaPoet生成 .java源文件的Java
- Android APT开发教程 二 JavaPoet生成 .java源文件的Java API
- Android APT开发教程 五 使用注释完成findViewById和setConten
- Android APT开发教程 六 使用注解替代setOnClickListener还有注释
- 写给VR手游开发小白的教程:(五)Cardboard插件与Android之间的通信交互
- Android APT开发教程 六 使用注解替代setOnClickListener还有注释给String赋值
- Android开发视频教程之三十一(代码编写 三)
- 【Android游戏开发之五】游戏注册界面Demo-实现两个Activity之间的切换与数据交互!
- Android开发视频教程之三十四(代码编写 六)
- Android开发视频教程之二十九(代码编写 一)
- 【风宇冲】Unity3D教程宝典之 C#代码注释规范及文档生成
- Android 日历开发教程[七] 修正后代码下载
- 【Android 开发教程】在Activity和Service之间建立链接
- 【代码】android软件开发 Service Binder交互通信实例
- Android简明开发教程二十四:总结及示例代码下载
- Android开发——不同Activity之间的信息交互
- Android应用开发教程:两个运行的Activity之间的通信
- Android简明开发教程二十四:总结及示例代码下载