https://blog.csdn.net/cpcpcp123/category_9620735.html
Q:APT原理是什么,怎么被执行起来的?
A:在javac编译时,先通过SPI机制加载所有的APT实现类,并将解析到需要编译的java源文件中所有的注解信息,与APT声明的支持处理的注解信息进行匹配,若待编译的源文件中存在APT声明的注解,则调起APT实现类的process方法。
Q:APT中process方法到底执行几次?为什么这么设计?
A:最少执行两次,最多无数次。最后一次执行可以视为Finish结束通知,执行收尾工作。
Q:APT中process方法boolean返回值返回true或者false有什么影响?
A: true:声明的注解只能被当前APT处理;false:在当前APT处理完声明的注解后,仍能被其他APT处理
1:不同module 之间Activity跳转处理器
1.1:定义注解
针对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();
}
1.2:编码处理器RouterProcessor
@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();
}
1.3: 生成APT源码
1.3.1 在APP主module中生成 RouterManager.java源码
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();
}
}
1.3.2:在Shop module中,生成Router_shop.java源码
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);
}
}
1.3.3:在bbs module中,生成Router_bbs.java源码
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);
}
}
}
2:仿ButterKnife给Activity各控件绑定Id
2.1 : 定义注解
// 保留到编译阶段,不加载进JVM
@Retention(RetentionPolicy.CLASS)
// 作用对象
@Target(ElementType.FIELD)
public @interface BindView {
int value(); // 属性名为value的int 变量
}
2.2 :编码注解处理器
@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();
}
}
2.3 生成注解文件
package org.loader.module2module;
public class MainActivityViewBinding {
public static void bind(MainActivity _mainActivity) {
_mainActivity.tv = (android.widget.TextView)(_mainActivity.findViewById(2131165313));}
}