赞
踩
https://blog.csdn.net/cpcpcp123/category_9620735.html
A:在javac编译时,先通过SPI机制加载所有的APT实现类,并将解析到需要编译的java源文件中所有的注解信息,与APT声明的支持处理的注解信息进行匹配,若待编译的源文件中存在APT声明的注解,则调起APT实现类的process方法。
A:最少执行两次,最多无数次。最后一次执行可以视为Finish结束通知,执行收尾工作。
A: true:声明的注解只能被当前APT处理;false:在当前APT处理完声明的注解后,仍能被其他APT处理
- 针对BBS和shop以及主module各模块之间跳转,我们定义四个注解
-
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.CLASS)
- public @interface AutoRouter {
- }
-
-
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.CLASS)
- public @interface Component {
- String value();
- }
-
-
- @Retention(RetentionPolicy.CLASS)
- @Target(ElementType.TYPE)
- public @interface Components {
- String[] value();
- }
-
-
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.CLASS)
- public @interface StaticRouter {
- String value();
- }
-
-
-

- @AutoService(Processor.class)
- public class RouterProcessor extends AbstractProcessor {
-
- private Filer mFiler;
- private Messager mMessager;
-
- private Map<String, String> mStaticRouterMap = new HashMap<>();
- private List<String> mAutoRouterList = new ArrayList<>();
-
- @Override
- public synchronized void init(ProcessingEnvironment processingEnvironment) {
- super.init(processingEnvironment);
- mFiler = processingEnvironment.getFiler();
- mMessager = processingEnvironment.getMessager();
- }
-
- @Override
- public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.latestSupported();
- }
-
- @Override
- public Set<String> getSupportedAnnotationTypes() {
- Set<String> set = new HashSet<>();
- set.add(AutoRouter.class.getCanonicalName());
- set.add(StaticRouter.class.getCanonicalName());
- set.add(Component.class.getCanonicalName());
- set.add(Components.class.getCanonicalName());
- return set;
- }
-
- @Override
- public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
- mStaticRouterMap.clear();
- mAutoRouterList.clear();
-
- try {
- Set<? extends Element> mainAppElement = roundEnvironment.getElementsAnnotatedWith(Components.class);
- if (!mainAppElement.isEmpty()) {
- processInstaller(mainAppElement);
- return true;// 第一轮执行APT (创建 APP module对应的 注解类)
- }
- // 第二轮或者第三轮执行APT (创建 bbslib 和 shoplib module对应的 注解类)
- processComponent(roundEnvironment);
- } catch (Exception e) {
- mMessager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
- }
-
- return true;
- }
-
- private void processInstaller(Set<? extends Element> mainAppElement) throws IOException {
- TypeElement typeElement = (TypeElement) mainAppElement.iterator().next();
- JavaFileObject javaFileObject = mFiler.createSourceFile(Config.ROUTER_MANAGER, typeElement); // RouterManager
- PrintWriter writer = new PrintWriter(javaFileObject.openWriter());
-
- writer.println("package " + Config.PACKAGE_NAME + ";"); // org.loader.router
- writer.println("import org.loader.router.Router_shop;");// 导包 router_shop
- writer.println("import org.loader.router.Router_bbs;");// 导包 Router_bbs
- writer.println("public class " + Config.ROUTER_MANAGER + " {"); // RouterManager
- writer.println("public static void " + Config.ROUTER_MANAGER_METHOD + "() {");// setup
-
- Components componentsAnnotation = typeElement.getAnnotation(Components.class);
- String[] components = componentsAnnotation.value();
- for (String item : components) {
- writer.println(Config.FILE_PREFIX + item + ".router();"); //Router_
- }
-
- writer.println("}");
- writer.println("}");
-
- writer.flush();
- writer.close();
- }
-
- private void processComponent(RoundEnvironment roundEnvironment) throws Exception {
- Set<? extends Element> compElements = roundEnvironment.getElementsAnnotatedWith(Component.class);
- if (compElements.isEmpty()) { return;}
-
- Element item = compElements.iterator().next();
- String componentName = item.getAnnotation(Component.class).value();
-
- Set<? extends Element> routerElements = roundEnvironment.getElementsAnnotatedWith(StaticRouter.class);
- for (Element e : routerElements) {
- if (! (e instanceof TypeElement)) { continue;}
- TypeElement typeElement = (TypeElement) e;
- String pattern = typeElement.getAnnotation(StaticRouter.class).value();
- mStaticRouterMap.put(pattern, typeElement.getQualifiedName().toString());
- }
-
- Set<? extends Element> autoRouterElements = roundEnvironment.getElementsAnnotatedWith(AutoRouter.class);
- for (Element e : autoRouterElements) {
- if (!(e instanceof TypeElement)) { continue;}
- TypeElement typeElement = (TypeElement) e;
- mAutoRouterList.add(typeElement.getQualifiedName().toString());
- }
-
- writeComponentFile(componentName);
- }
-
- private void writeComponentFile(String componentName) throws Exception {
- String className = Config.FILE_PREFIX + componentName;// Router_
- JavaFileObject javaFileObject = mFiler.createSourceFile(className);
- // javaFileObject.delete();
-
- PrintWriter printWriter = new PrintWriter(javaFileObject.openWriter());
-
- printWriter.println("package " + Config.PACKAGE_NAME + ";");
-
- printWriter.println("import android.app.Activity;");
- printWriter.println("import android.app.Service;");
- printWriter.println("import android.content.BroadcastReceiver;");
-
- printWriter.println("public class " + className + " {");
- printWriter.println("public static void router() {");
-
- // // Router.router(ActivityRule.ACTIVITY_SCHEME + "shop.main", ShopActivity.class);
- for(Map.Entry<String, String> entry : mStaticRouterMap.entrySet()) {
- printWriter.println("org.loader.router.Router.router(\"" + entry.getKey()
- +"\", "+entry.getValue()+".class);");
- }
-
- for (String klass : mAutoRouterList) {
- printWriter.println("if (Activity.class.isAssignableFrom(" + klass + ".class)) {");
- printWriter.println("org.loader.router.Router.router(org.loader.router.rule.ActivityRule.ACTIVITY_SCHEME + \""
- +klass+"\", " + klass + ".class);");
- printWriter.println("}");
-
- printWriter.println("else if (Service.class.isAssignableFrom(" + klass + ".class)) {");
- printWriter.println("org.loader.router.Router.router(org.loader.router.rule.ServiceRule.SERVICE_SCHEME + \""
- +klass+"\", " + klass + ".class);");
- printWriter.println("}");
-
- printWriter.println("else if (BroadcastReceiver.class.isAssignableFrom(" + klass + ".class)) {");
- printWriter.println("org.loader.router.Router.router(org.loader.router.rule.ReceiverRule.RECEIVER_SCHEME + \""
- +klass+"\", "+klass+".class);");
- printWriter.println("}");
- }
-
- printWriter.println("}");
- printWriter.println("}");
- printWriter.flush();
- printWriter.close();
- }

- package org.loader.router;
- import org.loader.router.Router_shop;
- import org.loader.router.Router_bbs;
- public class RouterManager {
- public static void setup() {
- Router_shop.router();
- Router_bbs.router();
- }
- }
- package org.loader.router;
- import android.app.Activity;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- public class Router_shop {
- public static void router() {
- org.loader.router.Router.router("activity://shop.main", org.loader.shoplib.ShopActivity.class);
- }
- }
- package org.loader.router;
- import android.app.Activity;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- public class Router_bbs {
- public static void router() {
- if (Activity.class.isAssignableFrom(org.loader.bbslib.BBSActivity.class)) {
- org.loader.router.Router.router(org.loader.router.rule.ActivityRule.ACTIVITY_SCHEME + "org.loader.bbslib.BBSActivity", org.loader.bbslib.BBSActivity.class);
- }
- else if (Service.class.isAssignableFrom(org.loader.bbslib.BBSActivity.class)) {
- org.loader.router.Router.router(org.loader.router.rule.ServiceRule.SERVICE_SCHEME + "org.loader.bbslib.BBSActivity", org.loader.bbslib.BBSActivity.class);
- }
- else if (BroadcastReceiver.class.isAssignableFrom(org.loader.bbslib.BBSActivity.class)) {
- org.loader.router.Router.router(org.loader.router.rule.ReceiverRule.RECEIVER_SCHEME + "org.loader.bbslib.BBSActivity", org.loader.bbslib.BBSActivity.class);
- }
- }
- }

- // 保留到编译阶段,不加载进JVM
- @Retention(RetentionPolicy.CLASS)
- // 作用对象
- @Target(ElementType.FIELD)
- public @interface BindView {
- int value(); // 属性名为value的int 变量
- }
- @SuppressWarnings("unused")
- @AutoService(Processor.class)
- public class BindViewProcessor extends AbstractProcessor {
- // Element代表程序的元素,例如包、类、方法。
- private Elements elementUtils;
-
- @Override
- public synchronized void init(ProcessingEnvironment processingEnvironment) {
- super.init(processingEnvironment);
- elementUtils = processingEnvironment.getElementUtils();
- }
-
- /**
- * @return 指定java版本。
- */
- @Override
- public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.latestSupported();
- }
-
- /**
- * 指定该目标的注解对象,指定注解处理器是注册给哪个注解的,返回指定支持的注解类集合。
- *
- * @return Set<String> getCanonicalName即包名.类名,不同的对象获取的值不同,可能为空
- */
- @Override
- public Set<String> getSupportedAnnotationTypes() {
- Set<String> hashSet = new HashSet<>();
- hashSet.add(BindView.class.getCanonicalName());
- return hashSet;
- }
-
- /**
- * 处理包含指定注解对象的代码元素
- * 获取控件变量的引用以及对应的viewId,先遍历出每个Activity所包含的所有注解对象
- *
- * @param set Set<? extends TypeElement>
- * @param roundEnvironment RoundEnvironment 所有注解的集合
- * @return true
- */
- @Override
- public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
- // 获取所有包含BindView注解的元素
- Set<? extends Element> elementSet = roundEnvironment.getElementsAnnotatedWith(BindView.class);
- // 此处的TypeElement就是Activity
- // Activity中包含的 id以及对应的属性(控件)
- Map<TypeElement, Map<Integer, VariableElement>> typeElementMapHashMap = new HashMap<>();
- for (Element element : elementSet) {
- // 注解的是FIELD,因此可以直接转换
- VariableElement variableElement = (VariableElement) element;
- // 获取最里层的元素,此处就是Activity
- TypeElement typeElement = (TypeElement) variableElement.getEnclosingElement();
- // 获取对应Activity中的Map viewId View
- Map<Integer, VariableElement> variableElementMap = typeElementMapHashMap.get(typeElement);
- if (variableElementMap == null) {
- variableElementMap = new HashMap<>();
- typeElementMapHashMap.put(typeElement, variableElementMap);
- }
- // 获取注解对象
- BindView bindView = variableElement.getAnnotation(BindView.class);
- // 获取注解值
- int id = bindView.value();
- variableElementMap.put(id, variableElement);
- }
-
- for (TypeElement key : typeElementMapHashMap.keySet()) {
- Map<Integer, VariableElement> elementMap = typeElementMapHashMap.get(key);
- String packageName = elementUtils.getPackageOf(key).getQualifiedName().toString();
-
- JavaFile javaFile = JavaFile.builder(packageName, generateCodeByPoet(key,
- elementMap)).build();
- try {
- javaFile.writeTo(processingEnv.getFiler());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- return true;
- }
-
- private TypeSpec generateCodeByPoet(TypeElement typeElement, Map<Integer, VariableElement> variableElementMap) {
- //自动生成的文件以 Activity名 + ViewBinding 进行命名
- return TypeSpec.classBuilder(typeElement.getSimpleName().toString() + "ViewBinding")
- .addModifiers(Modifier.PUBLIC)
- .addMethod(generateMethodByPoet(typeElement, variableElementMap))
- .build();
- }
-
- /**
- * @param typeElement 注解对象的根元素,即Activity
- * @param variableElementMap Activity包含的注解对象以及注解的目标对象
- * @return MethodSpec
- */
- private MethodSpec generateMethodByPoet(TypeElement typeElement, Map<Integer, VariableElement> variableElementMap) {
- ClassName className = ClassName.bestGuess(typeElement.getQualifiedName().toString());
- // _mainActivity.btn_serializeSingle = (android.widget.Button) (_mainActivity.findViewById(2131165221));
- // 第一个转小写+下划线
- String parameter = "_" + Utils.toLowerCaseFirstChar(className.simpleName());
- MethodSpec.Builder builder = MethodSpec.methodBuilder("bind") // 方法名
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC) // public static
- .returns(void.class)// 返回类型
- .addParameter(className, parameter);
- for (int viewId : variableElementMap.keySet()) {
- VariableElement variableElement = variableElementMap.get(viewId);
- // 变量名
- String fieldName = variableElement.getSimpleName().toString();
- // 变量父类的全称
- String fieldType = variableElement.asType().toString();
- String text = "{0}.{1} = ({2})({3}.findViewById({4}));";
- builder.addCode(MessageFormat.format(text, parameter, fieldName, fieldType, parameter, String.valueOf(viewId)));
- }
- return builder.build();
- }
- }

- package org.loader.module2module;
-
- public class MainActivityViewBinding {
- public static void bind(MainActivity _mainActivity) {
- _mainActivity.tv = (android.widget.TextView)(_mainActivity.findViewById(2131165313));}
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。